我在循环中做了几个NSURLSession请求。我想以与创建任务相同的顺序存储响应的结果。但是,由于完成处理程序在一个单独的线程中运行,有时会发生在对第一个任务的响应之前收到对第二个任务的响应。
如何确保我的响应与启动任务的顺序相同?
SQLiteOpenHelper
答案 0 :(得分:1)
虽然我不鼓励要求以特定顺序接收回复的行为,但您可以将回复(无论收到的顺序如何)整理成已知的顺序。
receivedData
数组应初始化,其容量应与将要发出的请求数相匹配:
var receivedData = [String](count: urlsAsString.count, repeatedValue: "")
然后,当您收到响应时,由于您位于可以访问请求index
的块中,您可以将响应数据直接添加到receivedData
数组的索引中:< / p>
receivedData[index] = result as (String)
完整代码如下:
var receivedData = [String](count: urlsAsString.count, repeatedValue: "")
for index in 0 ... urlsAsString.count-1 {
let myUrl = NSURL(string: urlsAsString[index])
var request = NSMutableURLRequest(URL: myUrl!)
// here I also set additional parameters (HTTPMethod, ...)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
responseData, response, error in
// here I handle the response
let result = ...
dispatch_async(dispatch_get_main_queue()) {
// Insert the result into the correct index
receivedData[index] = result
}
}
task.resume()
}
答案 1 :(得分:1)
因为您知道http请求的确切数量。
您可以创建一个大小为urls.count
的数组,然后将结果设置为完成处理程序,对应于每个循环中的索引。
receivedData = [String](count: urls.count, repeatedValue: "No Data")
for (index,url) in enumerate(urls){
let url = NSURL(string: url)!
let task = NSURLSession.sharedSession().dataTaskWithURL(url){ data, response, error in
if error != nil{
self.receivedData[index] = "error: \(error.localizedDescription)"
return
}
let result = ...
dispatch_async(dispatch_get_main_queue()) {
self.recivedData[index] = "\(result)"
}
}
task.resume()
}
答案 2 :(得分:0)
实际上,无法确定回复的顺序。 有两种解决方法:
一个接一个地发送请求,这意味着在返回上一个响应后发送下一个请求。您可以使用ReactiveCocoa使代码更优雅。或者使用我编写的网络库STNetTaskQueue,有一个STNetTaskChain可以一个接一个地处理请求。
并行发送请求(就是您现在正在做的事情),并使用NSDictionary跟踪请求和响应,在所有请求完成后,按原始顺序组合响应。
希望这有帮助!