Как убедиться, что у меня есть только 1 асинхронное соединение NSURLC одновременно? - PullRequest
1 голос
/ 07 августа 2011


Я создаю приложение, которое много общается с сервером.Я хочу убедиться, что у меня есть только 1 соединение за раз - только 1 запрос в ожидании.Я хочу, чтобы, если я попытаюсь отправить другой запрос, он будет ждать завершения текущего запроса, прежде чем отправлять следующий.

Как я могу реализовать это?
Tnx!

1 Ответ

1 голос
/ 07 августа 2011

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

...