Apple provides a sample project CustomHttpProtocol to demonstrate how NSURLProtocol works with NSURLSession.
Note the project includes a file QNSURLSessionDemux, which involves how NSURLSession' delegate works.
When creating a NSURLSession object from NSURLSessionConfiguration,
+ sessionWithConfiguration:delegate:delegateQueue:
a delegate of NSURLSessionDelegate can be specified in the delegate parameter. Apparently this delegate will be used to handle NSURLSessionDelegate event.
When creating the data task from the NSURLSession object, Apple defiends NSURLSessionDataDelegate and NSURLSessionTaskDelegate to handle the per task event. However, unlike NSURLSession, when creating the data task, there is no parameter in
- dataTaskWithRequest:completionHandler:
method to specify a delegate to handle the per task event. Instead the delegate object passed for creating NSURLSession will also be used to handle the per task delegate event.
Then the problem comes, as the delegate for NSURLSession is a shared delegate object for all data tasks, but each task has its own logic to handle the response data as well as mode and thread, so once the NSURLSession's common delegate get the per task delegate event, it has to find a way to route back to the per task delegate to handle it.
QNSURLSessionDemux in CustomHttpProtocol is created for this purpose, it keeps a dictionary of per task data delegate specified by application when the data task is created. Then the NSURLSessionDelegate will route the per task event their corresponding per task delegate.
Actually, NSURLSessionTaskDelegate and NSURLSessionDataDelegate are all derived from NSURLSessionDelegate, which implies the NSURLSession delegate will also be used to handle per task event.
One last note, when creating the data task, if custom delegate will be used to handle NSURLSession's data task event, then use the method that does not take the completionHandler. Otherwise, if completionHandler exists, then the default system delegate will be used, and custom delegate will not be invoked.
Note the project includes a file QNSURLSessionDemux, which involves how NSURLSession' delegate works.
When creating a NSURLSession object from NSURLSessionConfiguration,
+ sessionWithConfiguration:delegate:delegateQueue:
a delegate of NSURLSessionDelegate can be specified in the delegate parameter. Apparently this delegate will be used to handle NSURLSessionDelegate event.
When creating the data task from the NSURLSession object, Apple defiends NSURLSessionDataDelegate and NSURLSessionTaskDelegate to handle the per task event. However, unlike NSURLSession, when creating the data task, there is no parameter in
- dataTaskWithRequest:completionHandler:
method to specify a delegate to handle the per task event. Instead the delegate object passed for creating NSURLSession will also be used to handle the per task delegate event.
Then the problem comes, as the delegate for NSURLSession is a shared delegate object for all data tasks, but each task has its own logic to handle the response data as well as mode and thread, so once the NSURLSession's common delegate get the per task delegate event, it has to find a way to route back to the per task delegate to handle it.
QNSURLSessionDemux in CustomHttpProtocol is created for this purpose, it keeps a dictionary of per task data delegate specified by application when the data task is created. Then the NSURLSessionDelegate will route the per task event their corresponding per task delegate.
Actually, NSURLSessionTaskDelegate and NSURLSessionDataDelegate are all derived from NSURLSessionDelegate, which implies the NSURLSession delegate will also be used to handle per task event.
One last note, when creating the data task, if custom delegate will be used to handle NSURLSession's data task event, then use the method that does not take the completionHandler. Otherwise, if completionHandler exists, then the default system delegate will be used, and custom delegate will not be invoked.