I'm trying to write default behaviour for a delegate method using a Swift extension as below, but it is never called. Does anyone know why or how to do it the right way?
extension NSURLSessionDelegate {
public func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
//default behaviour here
}
}
Adding override
does not work either.
According to this, Apple's default implementation looks like:
extension NSURLSessionDelegate {
func URLSession(session: NSURLSession, didBecomeInvalidWithError error: NSError?) { }
func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) { }
}
My DataTask calls typically look like this:
let sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
sessionConfiguration.HTTPCookieStorage = NSHTTPCookieStorage.sharedHTTPCookieStorage()
let session = NSURLSession(configuration: sessionConfiguration)
let requestURL = NSURL(string:"https:www.google.com/blabla")
session.dataTaskWithURL(requestURL!, completionHandler: completion).resume()
Where completion
will typically be a Swift closure received via parameter.
I need to implement the URLSession(... didReceiveChallenge ...)
function for all nsurlsessiontask
implementations throughout my app, but can't set my session's delegate as I need to use the completionHandler (as mentioned in my comment below).
You can extends the NSURLSessionDelegate
protocol for adding default implementation, but your NSURLSession
objects needs a delegate.
This delegate can only be set using +sessionWithConfiguration:delegate:delegateQueue:
(since the delegate property is read only), so your only way to set it is to subclass NSURLSession
, override +sessionWithConfiguration:
and call the initializer with the delegate property. The issue here is that you have to replace all your NSURLSession
objects to MyCustomSessionClass
. objects.
I suggest you to create a SessionCreator class which will conforms to NSURLSessionDelegate
protocol and will create NSURLSession
objects. You still have to replace the creation of your objects, but at least the object isn't the delegate of itself.
public class SessionCreator:NSObject,NSURLSessionDelegate {
//MARK: - Singleton method
class var sharedInstance :SessionCreator {
struct Singleton {
static let instance = SessionCreator()
}
return Singleton.instance
}
//MARK: - Public class method
public class func createSessionWithConfiguration (configuration:NSURLSessionConfiguration) -> NSURLSession {
return sharedInstance.createSessionWithConfiguration(configuration)
}
//MARK: - Private methods
private func createSessionWithConfiguration (configuration:NSURLSessionConfiguration) -> NSURLSession {
return NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
}
//MARK: - NSURLSessionDelegate protocol conformance
public func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
// Always called since it's the delegate of all NSURLSession created using createSessionWithConfiguration
}
}
// Let create a NSURLSession object :
let session = SessionCreator.createSessionWithConfiguration(NSURLSessionConfiguration())