【发布时间】:2011-08-07 08:07:29
【问题描述】:
我正在创建一个与服务器进行大量通信的应用程序。我想确保我一次只有 1 个连接 - 只有 1 个请求待处理。我希望如果我尝试发送另一个请求,它将等到当前请求完成后再发送下一个请求。
我该如何实现这个?
天呐!
【问题讨论】:
标签: ios asynchronous request nsurlconnection
我正在创建一个与服务器进行大量通信的应用程序。我想确保我一次只有 1 个连接 - 只有 1 个请求待处理。我希望如果我尝试发送另一个请求,它将等到当前请求完成后再发送下一个请求。
我该如何实现这个?
天呐!
【问题讨论】:
标签: ios asynchronous request nsurlconnection
我不知道有什么自动机制可以做到这一点。所以你必须自己写一个新类(我们称之为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:。
【讨论】: