2016-11-30 84 views
1

创建并恢复NSURLSessionTask后,为什么NSURLSession操作队列为空?如何等待NSURLSession的所有任务完成?

有没有办法判断NSURLSession是否有待处理的任务?

目标是等待多个任务来完成,但是这并不工作:

NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithStreamedRequest:request]; 
[uploadTask resume]; 
// this prints "0" 
NSLog(self.session.delegateQueue.operationCount) 
// this returns immediately instead of waiting for task to complete 
[self.session.delegateQueue waitUntilAllOperationsAreFinished]; 
+0

OK,我可能已经发现,在https://github.com/AFNetworking/AFNetworking/issues/1504线索和https://stackoverflow.com/q/19414486/1033581有关事实'NSURLSession '不能单独用于配料。 –

+1

DispatchGroup是你需要的:)发现这个非常谷歌的结果链接http://commandshift.co.uk/blog/2014/03/19/using-dispatch-groups-to-wait-for-multiple-web-services/ –

回答

3

我找到了一个避免使会话失效的解决方案,使用建议的DispatchGroup

(答案是斯威夫特,而问题是ObjC ...但它是相同的逻辑)

需要注意的是,使用时uploadTaskWithStreamedRequest:,我们需要实现一个URLSessionTaskDelegatefunc urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)。所以,为了简化答案,我将演示DispatchGroupuploadTaskWithRequest:from:completionHandler:的用法。

// strong reference to the dispatch group 
let dispatchGroup = DispatchGroup() 

func performManyThings() { 
    for _ in 1...3 { 
     let request = URLRequest(url: URL(string: "http://example.com")!) 
     dispatchGroup.enter() 
     let uploadTask = self.session.uploadTask(with: request, from: nil) { [weak self] _, _, _ in 
      self?.dispatchGroup.leave() 
     } 
     uploadTask.resume() 
    } 
    dispatchGroup.notify(queue: .main) { 
     // here, all the tasks are completed 
    } 
} 
1

这很容易,只要你不关心重用会话,不介意做异步事情:

  • 呼叫finishTasksAndInvalidate在会话上。
  • 在会话委托中实现URLSession:didBecomeInvalidWithError:方法,以完成上一个任务完成后需要执行的任何工作。

这就是说,上面的代码的问题是,会话没有任何操作,直到它开始第一次获取,只要您的代码阻止运行循环,这不会发生。您通常不应该尝试同步使用NSURLSession。这几乎总是解决问题的错误方法。 :-)

+0

我已经提出了你的答案,因为我没有指定重用会话。真相是,我需要重用它,所以我接受了不同的答案。 –