我的代码有问题,我认为这可能与调用代码的顺序有关。
import WatchKit
import Foundation
class InterfaceController: WKInterfaceController {
private var tasks = [Task]()
override func willActivate() {
let taskUrl = "http://myjsonurl.com"
downloadJsonTask(url: taskUrl)
print(tasks.count) // EMPTY
super.willActivate()
}
func downloadJsonTask(url: String) {
var request = URLRequest(url: URL(string: url)!)
request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalCacheData
URLSession.shared.dataTask(with: request) { data, urlResponse, error in
guard let data = data, error == nil, urlResponse != nil else {
print("something is wrong")
return
}
do
{
let decoder = JSONDecoder()
let downloadedTasks = try decoder.decode(Tasks.self, from: data)
self.tasks = downloadedTasks.tasks
print(downloadedTasks.tasks.count) //4
} catch {
print("somehting went wrong after downloading")
}
}.resume()
}
}
我定义了private var tasks
,并用downloadJsonTask
函数填充它,但在函数运行后,print(tasks.count)
给出0。当我调用print(downloadedTasks.tasks.count)
时,它给出4。
我认为按时间顺序,当我打印任务变量时,它是空的,稍后会被填充
当您试图在willActivate((中打印任务数时,函数downloadJsonTask(url:String(尚未完成,因此您有空数组,因为任务尚未设置。
您应该向downloadJsonTask添加完成处理程序,如下所示:
(不要忘记将完成作为函数的参数(
func downloadJsonTask(url: String, completion: @escaping () -> Void) {
var request = URLRequest(url: URL(string: url)!)
request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalCacheData
URLSession.shared.dataTask(with: request) { data, urlResponse, error in
guard let data = data, error == nil, urlResponse != nil else {
print("something is wrong")
completion()
return
}
do {
let decoder = JSONDecoder()
let downloadedTasks = try decoder.decode(Tasks.self, from: data)
self.tasks = downloadedTasks.tasks
print(downloadedTasks.tasks.count) //4
} catch {
print("something went wrong after downloading")
}
completion() // This is moment when code which you write inside closure get executed
}.resume()
}
在你的willActivate((中使用这样的函数:
downloadJsonTask(url: taskUrl) {
print(tasks.count)
}
因此,这意味着当您获得数据时,大括号内的代码将被执行。
您的假设是正确的,即tasks
在首次打印时尚未分配值。
问题是网络请求是异步执行的。这意味着iOS不会等到downloadJsonTask(url:)
完成,而是立即继续执行代码(即在网络请求启动后立即调用print(tasks.count)
,而不等待它产生任何结果(。
URLSession.shared.dataTask(with:)
后面括号内的代码称为完成处理程序。一旦网络请求被竞争,就会执行此代码(因此得名(。只有当请求完成时,才会为tasks
变量分配一个值。您可以通过在self.tasks = downloadedTasks.tasks
:之后添加print(self.tasks.count)
来确保其工作
self.tasks = downloadedTasks.tasks
print(self.tasks)
print(downloadedTasks.tasks.count)