如何确保我一次只有1个异步NSURLConnection?

时间:2011-08-07 08:07:29

标签: ios asynchronous request nsurlconnection


我正在创建一个与服务器进行大量通信的应用程序。我想确保我一次只有一个连接 - 只有一个请求待处理。我想这样,如果我尝试发送另一个请求,它会等到当前的请求完成后再发送下一个请求。

我该如何实现呢? TNX!

1 个答案:

答案 0 :(得分:1)

我不知道有任何自动机制来做到这一点。所以你必须自己写一个新课(我们称之为ConnectionQueue):

基本上,不是直接创建NSURLConnection,而是调用ConnectionQueue类(应该只有一个实例)的方法,将NSURLRequest和委托作为参数。两者都被添加到队列中,即请求和委托的单独NSArray

如果数组只包含一个元素,则没有未完成的请求,您可以使用指定的请求创建NSURLConnection。但是,不是传递给方法的委托,而是将ConnectionQueue实例作为委托传递。结果,将通知连接队列有关连接的所有操作。在大多数情况下,您只需将回调转发给原始委托(您将在委托数组的第一个元素中找到它。)

但是,如果未完成的连接完成(调用connection:didFailWithError:connectionDidFinishLoading:),则首先调用原始委托,然后从两个阵列中删除连接。最后,如果数组不为空,则启动下一个连接。

<强>更新

这是一些代码。它编译但未经过其他测试。此外,NSURLConnectionDelegate协议的实施尚不完整。如果您期望的不仅仅是实现的回调,那么您必须添加它们。

标题文件:

#import <Foundation/Foundation.h>

@interface ConnectionQueue : NSObject {
    NSMutableArray *requestQueue;
    NSMutableArray *delegateQueue;
    NSURLConnection *currentConnection;
}

// Singleton instance
+ (ConnectionQueue *)sharedInstance;

// Cleanup and release queue
+ (void)releaseShared;

// Queue a new connection
- (void)queueRequest:(NSURLRequest *)request delegate:(id)delegate;

@end

<强>实施

#import "ConnectionQueue.h"


@implementation ConnectionQueue


static ConnectionQueue *sharedInstance = nil;


+ (ConnectionQueue*)sharedInstance
{
    if (sharedInstance == nil)
        sharedInstance = [[ConnectionQueue alloc] init];
    return sharedInstance;
}

+ (void)releaseShared
{
    [sharedInstance release];
    sharedInstance = nil;
}

- (id)init
{
    if ((self = [super init])) {
        requestQueue = [NSMutableArray arrayWithCapacity:8];
        delegateQueue = [NSMutableArray arrayWithCapacity:8];
    }
    return self;
}

- (void)dealloc
{
    [requestQueue release];
    [delegateQueue release];
    [currentConnection cancel];
    [currentConnection release];
    [super dealloc];
}

- (void)startNextConnection
{
    NSURLRequest *request = [requestQueue objectAtIndex:0];
    currentConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

- (void)queueRequest:(NSURLRequest *)request delegate:(id)delegate
{
    [requestQueue addObject:request];
    [delegateQueue addObject:delegate];
    if ([requestQueue count] == 1)
        [self startNextConnection];
}


- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    id delegate = [delegateQueue objectAtIndex:0];
    [delegate connection: connection didReceiveResponse: response];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    id delegate = [delegateQueue objectAtIndex:0];
    [delegate connection: connection didReceiveData: data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    id delegate = [delegateQueue objectAtIndex:0];
    [delegate connection: connection didFailWithError:error];
    [currentConnection release];
    currentConnection = nil;
    [requestQueue removeObjectAtIndex:0];
    [delegateQueue removeObjectAtIndex:0];

    if ([requestQueue count] >= 1)
        [self startNextConnection];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    id delegate = [delegateQueue objectAtIndex:0];
    [delegate connectionDidFinishLoading: connection];
    [currentConnection release];
    currentConnection = nil;
    [requestQueue removeObjectAtIndex:0];
    [delegateQueue removeObjectAtIndex:0];

    if ([requestQueue count] >= 1)
        [self startNextConnection];
}

@end

要使用连接队列,请创建 NSURLRequest 实例,然后调用:

[[ConnectionQueue sharedInstance] queueRequest:request delegate:self];

无需显式创建ConnectionQueue的单例实例。它将自动创建。但是,要正确清理,您应该在应用程序退出时调用[ConnectionQueue releaseShared],例如来自您的申请代表的applicationWillTerminate: