我正在创建一个与服务器进行大量通信的应用程序。我想确保我一次只有一个连接 - 只有一个请求待处理。我想这样,如果我尝试发送另一个请求,它会等到当前的请求完成后再发送下一个请求。
我该如何实现呢?
TNX!
答案 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:
。