iosnsurlsessionnsoperationqueuensurlsessiontask

How to wait for all tasks of an NSURLSession to complete?


Why is NSURLSession operation queue empty after creating and resuming an NSURLSessionTask?

Is there a way to tell if an NSURLSession has tasks pending?

The goal is to wait for multiple tasks to complete, but this doesn't work:

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];

Solution

  • I found a solution that avoids invalidating the session, using the suggested DispatchGroup.

    (answer is in Swift, while question is in ObjC ... but it's the same logic)

    Note that when using, uploadTaskWithStreamedRequest:, we need to implement an URLSessionTaskDelegate and func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?). So, to simplify the answer, I will demonstrate the use of DispatchGroup with uploadTaskWithRequest: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
        }
    }