当前位置:  开发笔记 > IOS > 正文

管理多个异步NSURLConnection连接

如何解决《管理多个异步NSURLConnection连接》经验,为你挑选了5个好方法。

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

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

异步请求的问题是当你有各种请求消失,并且你有一个委托指定将它们全部视为一个实体时,许多分支和丑陋的代码开始形成:

我们回来了什么样的数据?如果它包含这个,那就做,否则做其他.我认为能够标记这些异步请求会很有用,就像你能够使用ID标记视图一样.

我很好奇什么策略对于管理处理多个异步请求的类最有效.



1> Matt Gallagh..:

我跟踪由与之关联的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];
}


Aldi ...它*是*线程安全的,只要你从同一个线程启动所有连接(你可以通过使用performSelector调用你的启动连接方法来轻松完成:onThread:withObject:waitUntilDone :).如果尝试启动比队列的最大并发操作更多的连接(操作排队而不是并发运行),则将所有连接放在NSOperationQueue中会有不同的问题.NSOperationQueue适用于CPU绑定操作,但对于网络绑定操作,最好使用不使用固定大小线程池的方法.
如果从多个线程调用委托,则这不是线程安全的.您必须使用互斥锁来保护数据结构.更好的解决方案是继承NSURLConnection并将响应和数据引用添加为实例变量.我在Nocturne的问题中提供了一个更详细的解答:http://stackoverflow.com/questions/1192294/cocoa-any-checks-required-for-multiple-asynchronous-nsurlconnections

2> 小智..:

我有一个项目,我有两个不同的NSURLConnections,并希望使用相同的委托.我所做的是在我的类中创建两个属性,每个连接一个.然后在委托方法中,我检查它是否是哪个连接

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

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



3> Pat Niemeyer..:

对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块中需要它的方法,如图所示



4> petershine..:

这不是一个新的答案.请让我看看我怎么做的

为了在同一个类的委托方法中区分不同的NSURLConnection,我使用NSMutableDictionary来设置和删除NSURLConnection,使用其(NSString *)descriptionas键.

我选择的对象setObject:forKey是用于启动的唯一URL NSURLRequestNSURLConnection用途.

一旦设置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]];



5> Brad The App..:

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

推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有