迅速-函数顺序-哪个代码何时运行?

时间:2018-11-10 20:48:35

标签: swift watchkit

我的代码有问题,我认为这可能与代码的调用顺序有关。

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。

我认为按时间顺序打印时task变量为空,以后再填充。

2 个答案:

答案 0 :(得分:0)

当您尝试在willActivate()中打印任务数时,功能downloadJsonTask(url:String)尚未完成,因此您有空数组,因为尚未设置任务。

您应该像这样添加完成处理程序以下载JsonTask:

(不要忘记将完成作为函数的参数传递)

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)
}

因此,这意味着当您获取数据时,花括号中的代码将被执行。

答案 1 :(得分:0)

您正确的假设是,tasks在首次打印时尚未分配值。

问题是网络请求是异步执行的。这意味着iOS不会等到downloadJsonTask(url:)完成后才立即执行代码(即,它在网络请求启动之后立即调用print(tasks.count),而没有等待它执行产生任何结果。

URLSession.shared.dataTask(with:)之后方括号内的代码段称为补全处理程序。一旦网络请求得到竞争,该代码即被执行(因此命名)。仅在请求完成时才为变量tasks分配一个值。您可以通过在print(self.tasks.count)之后添加self.tasks = downloadedTasks.tasks来确保其有效:

self.tasks = downloadedTasks.tasks
print(self.tasks)
print(downloadedTasks.tasks.count)