2014-12-22 2 views
3

사용자 정의 NSURLProtocol을 구현 중이며 내부적으로 NSURLConnection 대신 데이터 작업을 사용하여 NSURLSession을 사용하려고합니다.NSURLSessionTask 인증 시도 완료 completionHandler 및 NSURLAuthenticationChallenge 클라이언트

재미있는 문제가 발생했으며 챌린지 처리기의 내부 구현에 대해 NSURLSession/NSURLSessionTask에 대해 궁금합니다.

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

나는 기본적으로 두 개의 서로 다른 도전 핸들러, 제공하고 하나되는 문제를 처리하기 위해 필요한 모든 정보를 제공하지만, 거의 해당 메소드가 기존 NSURLAuthenticationChallenge.client도 존재하는 completionHandler 블록, completionHandler 정보 옵션이있는 일대일

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

내 질문은 :

내가 프로토콜을 개발하고, 및 구현하기 위해 호출 API에 대한 위로 URL 로딩 시스템을 특정 인증 문제를 통과하고 싶은 때문에, 나는 NSURLSession 클라이언트 방법을 사용합니다 completionHandlerNSURLAuthenticationChallenge.client의 내부 구현이 같은지 여부에 관계없이 위임 메서드에서 완료 핸들러를 호출하지 않고 URL 로딩 시스템에서 적절한 NSURLAuthenticationChallenge.client 메서드를 호출 할 것을 기대할 수 있습니까?

답변

5

내 자신의 질문에 대답하려면 대답은 아니오입니다.

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

내 솔루션은 래퍼 만드는 것이었다 : 또한, 클라이언트가 도전에 응답하려고 할 때 애플의 제공 도전 보낸 따라서 충돌, 전체 NSURLAuthenticationChallengeSender 프로토콜을 구현하지 않습니다

@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 하위 클래스에서 똑같은 메서드를 구현하고 self를 챌린지 발신자로 전달하는 것 사이에는 차이가 없습니다. 이는 의사가해야한다고 말한 것입니다. 왜 그 메소드를 구현해야하는지 확신 할 수 없습니다. 아마도 버그 일 것입니다. 파일을 하나 만들어야합니다.하지만 NSURLProtocol 서브 클래스를 다른 객체가 아닌 보낸 사람으로 전달해야합니다. – dgatwood

관련 문제