Я не знаю ни одного автоматического механизма для этого.Таким образом, вы должны написать новый класс самостоятельно (назовем его 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:
вашего делегата приложения.