pipe理多个asynchronousNSURLConnection连接

我在课堂上有很多重复的代码,如下所示:

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 

asynchronous请求的问题是,当你有各种各样的请求时,你有一个委托给他们作为一个实体,很多分支和丑陋的代码开始制定:

我们回来了什么样的数据? 如果它包含这个,那么做别的。 我认为能够标记这些asynchronous请求非常有用,就像您可以使用ID标记视图一样。

我很好奇什么策略对于pipe理处理多个asynchronous请求的类来说效率最高。

我跟踪由与其关联的NSURLConnection键入的CFMutableDictionaryRef中的响应。 即:

 connectionToInfoMapping = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 

这可能看起来很奇怪,而不是NSMutableDictionary,但我这样做,因为此CFDictionary只保留其键(NSURLConnection),而NSDictionary复制其键(和NSURLConnection不支持复制)。

一旦完成:

 CFDictionaryAddValue( connectionToInfoMapping, connection, [NSMutableDictionary dictionaryWithObject:[NSMutableData data] forKey:@"receivedData"]); 

现在我有一个关于每个连接的数据的“信息”字典,我可以使用它来跟踪有关连接的信息,“信息”字典中已经包含一个可用于存储回复数据的可变数据对象。

 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { NSMutableDictionary *connectionInfo = CFDictionaryGetValue(connectionToInfoMapping, connection); [[connectionInfo objectForKey:@"receivedData"] appendData:data]; } 

我有一个项目,我有两个不同的NSURLConnections,并希望使用相同的代表。 我所做的是在我的课堂上创build两个属性,每个连接一个。 然后在委托方法中,我检查是否是连接

 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { if (connection == self.savingConnection) { [self.savingReturnedData appendData:data]; } else { [self.sharingReturnedData appendData:data]; } } 

这也允许我在需要时按名称取消特定的连接。

inheritanceNSURLConnection来保存数据是干净的,比其他一些答案less的代码,更加灵活,而且对参考pipe理的要求也较less。

 // DataURLConnection.h #import <Foundation/Foundation.h> @interface DataURLConnection : NSURLConnection @property(nonatomic, strong) NSMutableData *data; @end // DataURLConnection.m #import "DataURLConnection.h" @implementation DataURLConnection @synthesize data; @end 

像使用NSURLConnection一样使用它,并在其数据属性中累积数据:

 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { ((DataURLConnection *)connection).data = [[NSMutableData alloc] init]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [((DataURLConnection *)connection).data appendData:data]; } 

而已。

如果你想进一步,你可以添加一个块作为一个callback只有几行代码:

 // Add to DataURLConnection.h/.m @property(nonatomic, copy) void (^onComplete)(); 

像这样设置:

 DataURLConnection *con = [[DataURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; con.onComplete = ^{ [self myMethod:con]; }; [con start]; 

并在加载完成后调用它:

 - (void)connectionDidFinishLoading:(NSURLConnection *)connection { ((DataURLConnection *)connection).onComplete(); } 

您可以扩展该块来接受参数,或者只是将DataURLConnection作为parameter passing给在no-args块内需要它的方法,如图所示

这不是一个新的答案。 请让我告诉你我是怎么做的

为了区分同一个类的委托方法中不同的NSURLConnection,我使用NSMutableDictionary来设置和删除NSURLConnection,使用它的(NSString *)description作为关键字。

我为setObject:forKeyselect的对象是用于启动NSURLRequestNSURLConnection使用的唯一URL。

一旦设置NSURLConnection被评估为

 -(void)connectionDidFinishLoading:(NSURLConnection *)connection, it can be removed from the dictionary. // This variable must be able to be referenced from - (void)connectionDidFinishLoading:(NSURLConnection *)connection NSMutableDictionary *connDictGET = [[NSMutableDictionary alloc] init]; //...// // You can use any object that can be referenced from - (void)connectionDidFinishLoading:(NSURLConnection *)connection [connDictGET setObject:anyObjectThatCanBeReferencedFrom forKey:[aConnectionInstanceJustInitiated description]]; //...// // At the delegate method, evaluate if the passed connection is the specific one which needs to be handled differently if ([[connDictGET objectForKey:[connection description]] isEqual:anyObjectThatCanBeReferencedFrom]) { // Do specific work for connection // } //...// // When the connection is no longer needed, use (NSString *)description as key to remove object [connDictGET removeObjectForKey:[connection description]]; 

我采取的一种方法是不使用相同的对象作为委托为每个连接。 相反,我为每个被触发的连接创build了一个新的parsing类实例,并将委托设置为该实例。

试试我的自定义类, MultipleDownload ,它为您处理所有这些。

我通常会创build一个字典arrays。 每个字典都有一些识别信息,一个存储响应的NSMutableData对象,以及连接本身。 当连接委托方法触发时,我查找连接的字典并相应地处理它。

一个select就是自己inheritanceNSURLConnection并添加一个-tag或类似的方法。 NSURLConnection的devise是故意非常裸露的骨头,所以这是完全可以接受的。

或者也许你可以创build一个负责创build和收集连接数据的MyURLConnectionController类。 一旦加载完成,它只需要通知你的主控制器对象。

在iOS5及以上版本中,您可以使用类方法sendAsynchronousRequest:queue:completionHandler:

由于响应在完成处理程序中返回,因此无需跟踪连接。

我喜欢ASIHTTPRequest 。

正如其他答案所指出的那样,你应该将connectionInfo存储在某个地方,并通过连接来查找它们。

最自然的数据types是NSMutableDictionary ,但不能接受NSURLConnection作为键,因为连接是不可复制的。

NSMutableDictionary使用NSURLConnections作为键的另一种select是使用NSValue valueWithNonretainedObject]

 NSMutableDictionary* dict = [NSMutableDictionary dictionary]; NSValue *key = [NSValue valueWithNonretainedObject:aConnection] /* store: */ [dict setObject:connInfo forKey:key]; /* lookup: */ [dict objectForKey:key]; 

我决定inheritanceNSURLConnection并添加一个标记,委托和一个NSMutabaleData。 我有一个DataController类来处理所有的数据pipe理,包括请求。 我创build了一个DataControllerDelegate协议,以便单独的视图/对象可以监听DataController,以了解他们的请求何时完成,以及是否需要多less下载或错误。 DataController类可以使用NSURLConnection子类来启动一个新的请求,并保存要监听DataController的委托来知道请求何时完成。 这是我在XCode 4.5.2和iOS 6中的工作解决scheme。

声明DataControllerDelegate协议的DataController.h文件)。 DataController也是一个单例:

 @interface DataController : NSObject @property (strong, nonatomic)NSManagedObjectContext *context; @property (strong, nonatomic)NSString *accessToken; +(DataController *)sharedDataController; -(void)generateAccessTokenWith:(NSString *)email password:(NSString *)password delegate:(id)delegate; @end @protocol DataControllerDelegate <NSObject> -(void)dataFailedtoLoadWithMessage:(NSString *)message; -(void)dataFinishedLoading; @end 

DataController.m文件中的关键方法:

 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSURLConnectionWithDelegate *customConnection = (NSURLConnectionWithDelegate *)connection; NSLog(@"DidReceiveResponse from %@", customConnection.tag); [[customConnection receivedData] setLength:0]; } -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { NSURLConnectionWithDelegate *customConnection = (NSURLConnectionWithDelegate *)connection; NSLog(@"DidReceiveData from %@", customConnection.tag); [customConnection.receivedData appendData:data]; } -(void)connectionDidFinishLoading:(NSURLConnection *)connection { NSURLConnectionWithDelegate *customConnection = (NSURLConnectionWithDelegate *)connection; NSLog(@"connectionDidFinishLoading from %@", customConnection.tag); NSLog(@"Data: %@", customConnection.receivedData); [customConnection.dataDelegate dataFinishedLoading]; } -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { NSURLConnectionWithDelegate *customConnection = (NSURLConnectionWithDelegate *)connection; NSLog(@"DidFailWithError with %@", customConnection.tag); NSLog(@"Error: %@", [error localizedDescription]); [customConnection.dataDelegate dataFailedtoLoadWithMessage:[error localizedDescription]]; } 

并且开始一个请求: [[NSURLConnectionWithDelegate alloc] initWithRequest:request delegate:self startImmediately:YES tag:@"Login" dataDelegate:delegate];

NSURLConnectionWithDelegate.h:@protocol DataControllerDelegate;

 @interface NSURLConnectionWithDelegate : NSURLConnection @property (strong, nonatomic) NSString *tag; @property id <DataControllerDelegate> dataDelegate; @property (strong, nonatomic) NSMutableData *receivedData; -(id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately tag:(NSString *)tag dataDelegate:(id)dataDelegate; @end 

和NSURLConnectionWithDelegate.m:

 #import "NSURLConnectionWithDelegate.h" @implementation NSURLConnectionWithDelegate -(id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately tag:(NSString *)tag dataDelegate:(id)dataDelegate { self = [super initWithRequest:request delegate:delegate startImmediately:startImmediately]; if (self) { self.tag = tag; self.dataDelegate = dataDelegate; self.receivedData = [[NSMutableData alloc] init]; } return self; } @end 

每个NSURLConnection都有一个哈希属性,你可以通过这个属性区分所有的哈希属性。

例如,我需要在连接之前和之后保持某些信息,所以我的RequestManager有一个NSMutableDictionary来做到这一点。

一个例子:

 // Make Request NSURLRequest *request = [NSURLRequest requestWithURL:url]; NSURLConnection *c = [[NSURLConnection alloc] initWithRequest:request delegate:self]; // Append Stuffs NSMutableDictionary *myStuff = [[NSMutableDictionary alloc] init]; [myStuff setObject:@"obj" forKey:@"key"]; NSNumber *connectionKey = [NSNumber numberWithInt:c.hash]; [connectionDatas setObject:myStuff forKey:connectionKey]; [c start]; 

请求后:

 - (void)connectionDidFinishLoading:(NSURLConnection *)connection { NSLog(@"Received %d bytes of data",[responseData length]); NSNumber *connectionKey = [NSNumber numberWithInt:connection.hash]; NSMutableDictionary *myStuff = [[connectionDatas objectForKey:connectionKey]mutableCopy]; [connectionDatas removeObjectForKey:connectionKey]; }