TL:DR
.Completed
状态何时设置在NSURLSessionTask
上,它如何影响同一任务的completionHandler
?
是否有方法确保.Completed
状态仅在completionHandler
执行完成后设置?
问题
在这里关注另一个问题... 在Swift中链接多个异步函数
我被引导到高级NSOperations WWDC Talk 和 示例代码。
在将部分代码复制到我的项目后,我发现遇到竞争条件,情况取决于竞争条件如何发挥作用,有时会成功并有时会失败。
我创建的操作几乎与样品代码中的DownloadEarthquakesOperation
相同。
它是GroupOperation
的子类,并包含一个URLSessionTaskOperation
。使用completionHandler
创建NSURLSessionTask
处理下载的数据。
URLSessionTaskOperation
类通过观察其任务的state
属性,然后在更改为.Completed
时完成操作。
我遇到的问题是,在completionHandler
完成处理之前,似乎任务的state
已更改为.Completed
。
我有这样的完成处理程序...
// this is a direct copy of the sample code just using data task
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
self.downloadFinished(data, response: response as? NSHTTPURLResponse, error: error)
}
它调用的函数(伪代码)大致如下...(我目前无法访问确切的代码)。
func downloadFinished(data: NSData?, response: NSHTTPURLResponse?, error, NSError?) {
// if the error is not nil then finish operation with error
// if the response status code is not correct then finish with error
// try to convert the data to a JSON object using NSJSONSerialization
// finish with error if conversion failed
// get a single Int value out of the JSON object
// store the single Int value in an instance variable
}
这里没有异步代码。
在完成此操作后(相当于示例代码中的GetEarthquakesOperation
),此部分操作从实例变量中获取值并将其传递到下一个操作。
问题是有时该值存在,有时为nil。
通过在不同类中记录各种行,我可以看到网络操作在完成处理程序的执行过程中的某个时刻被设置为已完成。有时在值设置之前,有时在值设置之后。
令人困惑的是,我已经尝试在示例应用程序中强制发生这种情况,但无法做到。我尝试了sleep
执行处理程序和放入长时间执行循环,但两者似乎都无法解决问题。
有谁能帮助我修复这个竞态条件吗?
NSURLSessionDataTask
看起来对Completed
的定义与NSURLSessionDownloadTask
不同。这肯定是一个 bug 而不是预期行为。我也会提交一个 Radar。 - Erik Tjernlund