2014-12-22 2 views
3

Я реализую пользовательский NSURLProtocol и внутренне хочу использовать NSURLSession с задачами данных для внутренних сетей вместо NSURLConnection.Проверка подлинности аутентификации NSURLSessionTaskHandler и NSURLAuthenticationChallenge клиент

Я столкнулся с интересной проблемой и задаюсь вопросом о внутренней реализации обработчика проблем NSURLSession/NSURLSessionTask.

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

Здесь я в основном с двумя различными обработчиками вызова, один является completionHandler блока, который снабжен всей необходимой информацией, чтобы справиться с проблемой, но есть также наследие NSURLAuthenticationChallenge.client, который имеет методы, которые соответствуют в значительной степени один к одному с параметрами информации completionHandler.

Поскольку я занимаюсь разработкой протокола, и хотел бы передать определенные проблемы аутентификации вверх систему загрузки URL для вызова API для реализации, нужно использовать метод NSURLSession клиента:

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

Мой вопрос заключается в является ли внутренняя реализация completionHandler и NSURLAuthenticationChallenge.client одинаковой, и если да, могу ли я пропустить вызов обработчика завершения в методе делегирования с ожиданием, что система загрузки URL вызовет соответствующий метод NSURLAuthenticationChallenge.client?

ответ

5

Чтобы ответить на мой собственный вопрос, ответ отрицательный. Кроме того, если вызов отправителя Apple, не реализует весь NSURLAuthenticationChallengeSender протокол, таким образом, сбой, когда клиент пытается ответить на вызов:

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

Мое решение было создать обертку:

@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 

И я заменить связанного с новым, с использованием моего обернутого отправителя:

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

Предоставлено непрофессиональным отправителем? Вы имеете в виду базовый класс NSURLProtocol? – dgatwood

+0

Каждый объект-запрос имеет свойство отправителя, однако он прерывается для протоколов. –

+0

С точки зрения времени выполнения не может быть какой-либо разницы между передачей объекта challengeWrapper и реализацией тех же самых методов в вашем подклассе NSURLProtocol и передачей себя как отправителю вызова, что, как говорят документы, вам следует делать. Я не уверен, почему вы должны реализовать эти методы вообще - это, вероятно, ошибка, и вы должны подать один, но обычно вы должны передавать подкласс NSURLProtocol в качестве отправителя, а не другой объект. – dgatwood

Смежные вопросы