All of my networking code relies on the NSURLSession delegate methods--rather than completion handlers. My data & download tasks all work great, but my upload tasks never result in
URLSession:task:didCompleteWithError:
being called. However, the
URLSession:dataTask:didReceiveData:
and URLSession:dataTask:willCacheResponse:completionHandler:
delegate methods ARE called.
If I set the resource timeout to a really low value on my session object, then didCompleteWithErrors
does get called, but that's clearly not a solution.
Any ideas? I'm about to go insane here.
Thanks.
You will not see didCompleteWithError
called if you implement willCacheResponse
, but if the implementation fails to actually call the completionHandler
. You must call the completionHandler
.
The same is true with any and all of the various NSURLSession
delegate methods that provide a completionHandler
parameter (e.g. authentication challenges, redirects, etc.). If you implement these respective methods, you must ensure that the completionHandler
is called.
Another possibility someone may want to check in this case, is that your URLSession delegate methods are not marked private. If they are, the methods will not be called... this can be easy to do by accident if you leave modifiers off the methods, then use auto-fix on a warning to fix the modifiers for the method (makes it private).
Method signature should be:
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
Rob's answer is correct and gave me a big clue. However - for my specific problem - it didn't jump out at me why the NSURLSessionTaskDelegate
methods might not be called. If I could be allowed to provide another answer with a different focus.
Many of the NSURLSession
task creation methods have two variations; one with a completionHandler
parameter and one without.
For example:
func dataTaskWithRequest(_ request: NSURLRequest) -> NSURLSessionDataTask
func dataTaskWithRequest(_ request: NSURLRequest, completionHandler completionHandler: (NSData?, NSURLResponse?, NSError?) -> Void) -> NSURLSessionDataTask
If the completionHandler
method is used, then any delegate methods - in this case for NSURLSessionTaskDelegate
will be ignored. That's despite the fact that a delegate has been specified in the NSURLSession
initialiser.
The following Playground code demonstrates this. Toggle the task
declaration comments to see the delegate called or not:
import UIKit
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
class MyDelegate:NSObject, NSURLSessionTaskDelegate
{
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
NSLog("Delegate called")
}
}
let myDel = MyDelegate()
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config, delegate: myDel, delegateQueue: NSOperationQueue())
let url = NSURL(string: "http://httpbin.org")
let request: NSURLRequest = NSURLRequest(URL: url!)
// With completionHandler, delegate method above NOT called
let task : NSURLSessionDataTask = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
NSLog("Task done")
})
// Without completionHandler, delegate method above IS called
//let task : NSURLSessionDataTask = session.dataTaskWithRequest(request)
task.resume()
TLDR: tearing your hair out wondering why the NSURLSession
's delegate methods aren't called? User the alternative method signature to create your session tasks; that which omits the completionHandler parameter.
To expand upon another answer here, the NSURLSession docs state that either the completion handler or delegate methods will be called.
Like most networking APIs, the NSURLSession API is highly asynchronous. It returns data to your app in one of two ways, depending on the methods you call:
To a completion handler block that is called when a transfer finishes successfully or with an error.
By calling methods on the session’s delegate as data is received and when the transfer is complete.
A more specific ask of this question is here:
NSURLSession delegate and completionHandler
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With