Handler and NSURLAuthenticationChallenge client

I am implementing custom NSURLProtocol

and internally want to use NSURLSession

with data tasks for internal network instead NSURLConnection

.

I am facing an interesting problem and wondering about the internal implementation of the error handler NSURLSession

/ NSURLSessionTask

.

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
                            didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge 
                              completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler;

      

Here I am basically provided with two different request handlers, one of which is a block completionHandler

that is provided with all the necessary information to handle the call, but there is also a legacy NSURLAuthenticationChallenge.client

that has methods that pretty much match one-to-one with information parameters completionHandler

.

Since I am developing a protocol and want to pass certain authentication tasks up the url loading system for the calling API to implement, I need to use the client method NSURLSession

:

- (void)URLProtocol:(NSURLProtocol *)protocol didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;

      

My question is whether the internal implementation completionHandler

and NSURLAuthenticationChallenge.client

the same, and if so, can I miss a call completion handler method in a delegate, expecting the URL loading system will cause the appropriate NSURLAuthenticationChallenge.client

method?

+3


source to share


1 answer


To answer my own question, the answer is no. Moreover, Apple did not provide the job submitter with an implementation of the entire protocol NSURLAuthenticationChallengeSender

, so it crashes when the client tries to answer the call:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFURLSessionConnection performDefaultHandlingForAuthenticationChallenge:]: unrecognized selector sent to instance 0x7ff06d958410'

      

My solution was to create a wrapper:



@interface CPURLSessionChallengeSender : NSObject <NSURLAuthenticationChallengeSender>

- (instancetype)initWithSessionCompletionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler;

@end

@implementation CPURLSessionChallengeSender
{
    void (^_sessionCompletionHandler)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential);
}

- (instancetype)initWithSessionCompletionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
    self = [super init];

    if(self)
    {
        _sessionCompletionHandler = [completionHandler copy];
    }

    return self;
}

- (void)useCredential:(NSURLCredential *)credential forAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    _sessionCompletionHandler(NSURLSessionAuthChallengeUseCredential, credential);
}

- (void)continueWithoutCredentialForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    _sessionCompletionHandler(NSURLSessionAuthChallengeUseCredential, nil);
}

- (void)cancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
{
    _sessionCompletionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}

- (void)performDefaultHandlingForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    _sessionCompletionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
}

- (void)rejectProtectionSpaceAndContinueWithChallenge:(NSURLAuthenticationChallenge *)challenge
{
    _sessionCompletionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
}

@end

      

And I will replace the task object with a new one using my wrapped sender:

NSURLAuthenticationChallenge* challengeWrapper = [[NSURLAuthenticationChallenge alloc] initWithAuthenticationChallenge:challenge sender:[[CPURLSessionChallengeSender alloc] initWithSessionCompletionHandler:completionHandler]];
[self.client URLProtocol:self didReceiveAuthenticationChallenge:challengeWrapper];

      

+5


source







All Articles