2015-08-05 11 views
1

Я делаю несколько запросов NSURLSession в цикле. Я хотел бы сохранить результаты ответов в том же порядке, что и задачи. Но поскольку обработчик завершения работает в отдельном потоке, иногда бывает, что ответ на вторую задачу получает до ответа на первую задачу.Как убедиться, что ответы NSURLSession получены в том же порядке, что и запросы?

Как убедиться, что я получаю ответы в том же порядке, что и задачи запускаются?

var recivedData = [String]() 

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()) { 
      self.recivedData.append("\(result)") // save the result to array 
     } 
    } 
    task.resume() 
} 

ответ

1

В то время как я препятствовал бы поведению, которое требует ответов, которые будут получены в определенном порядке, вы можете сопоставить ответы (независимо от порядка их получения) в известном порядке.

receivedData массив должен быть инициализирован с мощностью, которая соответствует количеству запросов, которые будут сделаны:

var receivedData = [String](count: urlsAsString.count, repeatedValue: "") 

Затем, когда вы получите ответ, так как вы в блоке, который имеет доступ к index запроса вы можете добавить данные ответа непосредственно в индекс receivedData массива:

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

На самом деле, не может быть уверен в порядке ответов. Есть два пути для этого:

  1. направлять запросы один за другим, а это значит, отправить следующий запрос после того, как предыдущий ответ возвращается. Вы можете использовать ReactiveCocoa, чтобы ваши коды были элегантными. Или используйте сетевую библиотеку, которую я написал STNetTaskQueue, есть STNetTaskChain, который может обрабатывать запросы один за другим.

  2. Отправьте запросы параллельно (это то, что вы сейчас делаете), и используйте NSDictionary для отслеживания запроса и ответа после завершения всех запросов, объедините ответ в исходном порядке.

Надеюсь, это поможет!

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