2015-08-26 24 views
7

La mia applicazione utilizza NSURLConnection per comunicare con il server. Usiamo https per la comunicazione. Per gestire l'autenticazione da tutte le richieste in un posto ho usato NSURLProtocol e gestito l'autenticazione nei delegati in quella classe. Ora ho deciso di utilizzare NSURLSession anziché NSURLConnection. Sto cercando fatevi NSURLProtocol lavorare con NSURLSession ho creato un compito e usato NSURLProtocol daUtilizzo di NSURLProtocol con NSURLSession

NSMutableURLRequest *sampleRequest = [[NSMutableURLRequest alloc]initWithURL:someURL]; 
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; 
configuration.protocolClasses = @[[CustomHTTPSProtocol class]]; 
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; 
NSURLSessionDataTask *task = [session dataTaskWithRequest:checkInInfoRequest]; 
[task resume]; 

CustomHTTPSProtocol che è la mia classe NSURLProtocol assomiglia a questo

static NSString * const CustomHTTPSProtocolHandledKey = @"CustomHTTPSProtocolHandledKey"; 

@interface CustomHTTPSProtocol() <NSURLSessionDataDelegate,NSURLSessionTaskDelegate,NSURLSessionDelegate> 

@property (nonatomic, strong) NSURLSessionDataTask *connection; 
@property (nonatomic, strong) NSMutableData *mutableData; 

@end 

@implementation CustomHTTPSProtocol 

+ (BOOL)canInitWithRequest:(NSURLRequest *)request { 
    if ([NSURLProtocol propertyForKey:CustomHTTPSProtocolHandledKey inRequest:request]) { 
     return NO; 
    } 
    return [[[[request URL]scheme]lowercaseString]isEqualToString:@"https"]; 
} 

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { 
    return request; 
} 

- (void) startLoading { 
    NSMutableURLRequest *newRequest = [self.request mutableCopy]; 
    [NSURLProtocol setProperty:@YES forKey:CustomHTTPSProtocolHandledKey inRequest:newRequest]; 

    NSURLSession*session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil]; 
    self.connection = [session dataTaskWithRequest:newRequest]; 
    [self.connection resume]; 
    self.mutableData = [[NSMutableData alloc] init]; 
} 

- (void) stopLoading { 
    [self.connection cancel]; 
    self.mutableData = nil; 
} 

-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { 
    NSLog(@"challenge..%@",challenge.protectionSpace.authenticationMethod); 
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { 
     [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; 
    } 
    else { 
     [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; 
    } 
} 

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { 
    [self.client URLProtocol:self didLoadData:data]; 
    NSLog(@"data ...%@ ",data); //handle data here 
    [self.mutableData appendData:data]; 
} 

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { 
    if (!error) { 
     [self.client URLProtocolDidFinishLoading:self]; 
    } 
    else { 
     NSLog(@"error ...%@ ",error); 
     [self.client URLProtocol:self didFailWithError:error]; 
    } 
} 

@end 

Inizio di carico viene chiamato e anche richiesta di autenticazione è fatto ma interrompere il caricamento viene chiamato immediatamente dopo.

Codice di errore -999 "Annullato" viene restituito dopo un po 'di tempo. didReceiveData non viene chiamato.

Note:NSURLProtocol and the Authentication Process worked fine with NSURLConnection.

Che cosa mi manca ?? Le mie domande sono

  1. Registrazione [NSURLProtocol registerClass: [class CustomHTTPSProtocol]]; ha funzionato bene con NSURLConnection ma come resister per NSURLProtocol globalmente con NSURLSession?

  2. Perché le richieste non vengono soddisfatte in NSURLProtocol (stesso URL e logica funzionati conURLConnection) con URLSession e come ottenere NSURLProtocol che funziona con URLSession ?.

Gentilmente aiutarmi e fatemi sapere se volete altri dettagli.

risposta

0

so che questo è vecchio, ma il problema riscontrato è nel metodo didReceiveChallenge.Si stanno finendo il metodo chiamando

[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; 

o

[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; 

Quello che vi serve di fare invece utilizza il gestore di completamento per inviare i tuoi risultati. Sarebbe simile a questa:

completionHandler(.UseCredential, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust) 

o

completionHandler(.PerformDefaultHandling, nil) 

Questi sono a Swift 2.0, ma dovrebbe tradursi ben al Obj-C.

0

Il mio vago ricordo è che NSURLSession utilizza automaticamente tutti i protocolli registrati a livello globale. Quindi non dovresti aver bisogno di registrarlo di nuovo, ma non dovrebbe neanche farti male.

Mi chiedo se la richiesta dell'URL sia stata copiata, nel qual caso la codifica personalizzata potrebbe non funzionare e potresti vedere una ricorsione infinita finché non raggiunge un limite interno. Hai provato a impostare l'intestazione di una richiesta?

2

La registrazione di un NSURLProtocol personalizzato con NSUrlsession è uguale al modo in cui si utilizza NSURLConnection.

NSURLSession Api's (NSURLSessionDataTask e altre classi di attività) se utilizzato con NSUrlProtocol personalizzato non riesce a gestire correttamente le Sfide di autenticazione HTTP. Questo funzionava come previsto su iOS 7.x ed è rotto in iOS 8.x.Raised un radar Apple e il mio radar è stato chiuso dicendo che era un duplicato di un altro radar e continuo a vedere il radar originale è ancora aperto. Quindi credo che questo problema non sia stato ancora risolto da Apple ad oggi.

speranza non sono troppo in ritardo con la risposta :)

+0

Qualcuno sa se è stato risolto in iOS 9.xo 10.x? – Locksleyu

+0

Lo stato corrente del mio radar è ancora aperto, quindi credo che non sia stato ancora risolto in iOS 10.x. – Chandra