我班上有很多重复的代码,如下所示:
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
异步请求的问题是当你有各种请求消失,并且你有一个委托指定将它们全部视为一个实体时,许多分支和丑陋的代码开始形成:
我们回来了什么样的数据?如果它包含这个,那就做,否则做其他.我认为能够标记这些异步请求会很有用,就像你能够使用ID标记视图一样.
我很好奇什么策略对于管理处理多个异步请求的类最有效.
我跟踪由与之关联的NSURLConnection键入的CFMutableDictionaryRef中的响应.即:
connectionToInfoMapping = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
使用它代替NSMutableDictionary可能看起来很奇怪,但我这样做是因为这个CFDictionary只保留其键(NSURLConnection),而NSDictionary复制其键(NSURLConnection不支持复制).
一旦完成:
CFDictionaryAddValue( connectionToInfoMapping, connection, [NSMutableDictionary dictionaryWithObject:[NSMutableData data] forKey:@"receivedData"]);
现在我有一个"info"字典,用于每个连接,我可以用它来跟踪有关连接的信息,"info"字典已经包含一个可变数据对象,我可以用它来存储答复数据.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { NSMutableDictionary *connectionInfo = CFDictionaryGetValue(connectionToInfoMapping, connection); [[connectionInfo objectForKey:@"receivedData"] appendData:data]; }
我有一个项目,我有两个不同的NSURLConnections,并希望使用相同的委托.我所做的是在我的类中创建两个属性,每个连接一个.然后在委托方法中,我检查它是否是哪个连接
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { if (connection == self.savingConnection) { [self.savingReturnedData appendData:data]; } else { [self.sharingReturnedData appendData:data]; } }
这也允许我在需要时按名称取消特定连接.
对NSURLConnection进行子类化以保存数据是干净的,代码少于其他一些答案,更灵活,并且需要较少考虑参考管理.
// DataURLConnection.h #import@interface DataURLConnection : NSURLConnection @property(nonatomic, strong) NSMutableData *data; @end // DataURLConnection.m #import "DataURLConnection.h" @implementation DataURLConnection @synthesize data; @end
像使用NSURLConnection一样使用它并在其data属性中累积数据:
- (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]; }
而已.
如果你想更进一步,可以添加一个块作为回调,只需几行代码:
// 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作为参数传递给no-args块中需要它的方法,如图所示
这不是一个新的答案.请让我看看我怎么做的
为了在同一个类的委托方法中区分不同的NSURLConnection,我使用NSMutableDictionary来设置和删除NSURLConnection,使用其(NSString *)description
as键.
我选择的对象setObject:forKey
是用于启动的唯一URL NSURLRequest
的NSURLConnection
用途.
一旦设置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]];
我采取的一种方法是不为每个连接使用相同的对象作为委托.相反,我为每个被触发的连接创建一个新的解析类实例,并将委托设置为该实例.