2014-04-07 71 views
1

爲了使用ssl調用Web服務,我將子類NSURLConnection。 我想過要做到同步,而不僅僅是現在的異步連接。帶有ssl的同步子類NSURLConnection?

我的代碼:

#import "SecureSSLConnection.h" 

static NSMutableArray *sharedConnectionList = nil; 

@implementation SecureSSLConnection 
@synthesize request, completionBlock, internalConnection; 

- (id)initWithRequest:(NSMutableURLRequest *)req 
{ 
    self = [super init]; 
    if (self) { 
     self.request = req; 
    } 
    return self; 
} 

- (void)start 
{ 
    container = [NSMutableData new]; 
    internalConnection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:YES]; 

    if (!sharedConnectionList) { 
     sharedConnectionList = [NSMutableArray new]; 
    } 
    [sharedConnectionList addObject:self];  
} 

#pragma mark - NSURLConnectionDelegate 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    [container appendData:data]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    if (self.completionBlock) { 
     self.completionBlock(container, nil); 
    } 

    [sharedConnectionList removeObject:self]; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    if (self.completionBlock) { 
     self.completionBlock(nil, error); 
    } 

    [sharedConnectionList removeObject:self]; 
} 

#pragma mark - SSL Connection Addition 

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace 
{ 
    return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
{ 
    NSLog(@"challenge.protectionSpace.host: %@", challenge.protectionSpace.host); 

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { 
     // We only trust our own domain 
     if ([challenge.protectionSpace.host isEqualToString:WebSiteURL]) { 
      NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; 
      [challenge.sender useCredential:credential forAuthenticationChallenge:challenge]; 
     } 
    } 

    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; 
} 

我開始考慮實施:

+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error 

爲了保持同原來的委託。

一種方法是使用NSNotificationCenter,但我的目標是更容易的方法。

任何想法我應該怎麼做呢?

+0

你爲什麼繼承NSURLConnection?只是爲'sharedConnectionList'?你不需要提供你自己的代表。 – zaph

+0

@Zaph我同意共享連接數組結構很好奇,因爲子類「NSURLConnection」的概念。但我不確定爲什麼你反對他自己的委託實現,因爲(a)比調用'sendAsynchronousRequest'要好得多, (b)他的代表實際上正在處理認證挑戰。也許我不明白你想對代表說什麼。 – Rob

+1

我並不是反對代表的實現,而是指出子類化不是實現代表的必要條件。 – zaph

回答

2

我不會建議讓這個同步。你總是希望保持你的網絡請求異步。

簡單的解決方案是使用您的完成塊屬性。只需在第一個請求的完成塊中放入依賴於初始SSL請求的其他任務即可。這樣,他們不會開始,直到第一次完成。

更優雅的解決方案是更進一步,並將您的SSL請求包裝在併發NSOperation子類中。這樣,您不僅可以使用上述完成塊模式,還可以使用後續操作的addDependencyNSOperationQueuemaxConcurrentOperationCount來真正優化各種操作之間的動態。這是不平凡的,但你可以看到AFNetworking的一個相對深思熟慮的實現這種模式的例子。