2014-04-07 33 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的一个相对深思熟虑的实现这种模式的例子。