Прокси NSURLConnection NSURLRequest для асинхронных вызовов веб-сервиса

У меня есть несколько представлений, которые делают то же NSURLRequest/NSURLConnection request. Идеально, для получения некоторого повторного использования кода, я хотел бы иметь своего рода "прокси", который делает всю базовую работу создания/выполнения (асинхронного) запроса/соединения, установки все методы делегата, и т.д., таким образом, я не должен копировать все они NSURLConnection обработчики методов делегата в каждом представлении. В первую очередь, действительно ли этот подход дизайна разумен? Во-вторых, как я пошел бы о выполнении чего-то как этот?

Для небольшой вводной информации я делал попытку этого и заставил ее "работать", однако, это, кажется, не выполняется асинхронно. Я создал файл Proxy.h/m, который имеет методы экземпляра для различных вызовов веб-сервиса (и также содержит NSURLConnection методы делегата):

@interface Proxy : NSObject {

    NSMutableData *responseData;
    id<WSResponseProtocol> delegate;
}

- (void)searchForSomethingAsync:(NSString *)searchString delegate:(id<WSResponseProtocol>)delegateObj;

@property (nonatomic, retain) NSMutableData *responseData;
@property (assign) id<WSResponseProtocol> delegate;

@end

WSResponseProtocol определяется как таковой:

@protocol WSResponseProtocol <NSObject>

@optional
- (void)responseData:(NSData *)data;
- (void)didFailWithError:(NSError *)error;

@end

Для использования этого контроллер представления просто должен соответствовать WSResponseProtocol протокол, для ловли ответа (ответов). Совершение звонка веб-сервиса сделано как так:

Proxy *p = [[Proxy alloc] init];
[p searchForSomethingAsync:searchText delegate:self];
[p release];

Я могу предоставить больше кода, но остающееся может быть принято. Перед вызовом, я "startAnimating" a UIActivityIndicatorView счетчик. Но счетчик никогда не вращается. Если я просто поместил методы делегата NSURLConnection непосредственно в контроллер представления, то счетчик вращается. Так, это заставляет меня думать, что моя реализация не выполняется асинхронно. Какие-либо мысли/идеи здесь?

5
задан Jay Bhalani 18 July 2015 в 14:21
поделиться

2 ответа

Ваш подход разумен, однако, я не уверен, зачем вы создаете свой собственный протокол. В этом нет необходимости. Всё, что вам нужно, чтобы это реализовалось, находится в документации Apple по NSURLConnection. Если взять код с той страницы, где инстанцируется NSURLConnection, и сделать соединение ivar вместо того, чтобы просто создавать его в качестве локальной переменной, вы можете затем сравнить объекты соединения в каждом из методов обратного вызова и ответить соответствующим образом. Например, возьмите этот код из документации и измените объект соединения на ivar:

// create the request
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com/"]
                        cachePolicy:NSURLRequestUseProtocolCachePolicy
                    timeoutInterval:60.0];
// create the connection with the request
// and start loading the data
theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
    // Create the NSMutableData that will hold
    // the received data
    // receivedData is declared as a method instance elsewhere
    receivedData=[[NSMutableData data] retain];
} else {
    // inform the user that the download could not be made
}

Переменная theConnection - это наш ivar. Тогда вы можете проверить ее следующим образом:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    if (connection == theConnection)
    {
        // do something with the data object.
        [connectionSpecificDataObject appendData:data];
    }
}

Вы, конечно, можете реализовать ее, создав свой собственный протокол, как вы предлагаете, а затем перезвонить делегату, который соответствует вашему протоколу, но, возможно, вам лучше просто инстанцировать ваш объект, используя селектор успеха и неудачи, который вы можете проверить. Что-то вроде этого:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    if (connection == theConnection)
    {
        if (delegate && [delegate respondsToSelector:successSelector])
            [delegate performSelector:successSelector 
                           withObject:connectionSpecificDataObject];
    }
    [connection release];
}

Где dataDidDownloadSelector - это переменная SEL instance, которую вы устанавливаете, когда создаете делегата загрузки, где весь этот код содержится - ваш объект Proxy. Что-то вроде этого:

Proxy *p = [[Proxy alloc] init];
[p searchForSomethingAsync:searchText 
                  delegate:self 
           successSelector:@selector(didFinishWithData:) 
              failSelector:@selector(didFailWithError:)];

Реализуйте свои селекторы следующим образом:

- (void)didFinishWithData:(NSData*)data;
{
    // Do something with data
}

- (void)didFailWithError:(NSError*)error
{
    // Do something with error
}

Это стало более длинным ответом, чем я предполагал. Дайте мне знать, если это не имеет смысла, и я попробую прояснить.

С наилучшими пожеланиями,

.
22
ответ дан 18 December 2019 в 06:50
поделиться

Ваш код как есть, я думаю, ничего не сделает - вы освобождаете прокси сразу после инициализации, поэтому он даже не запускается.

Мне нравится использовать синхронные вызовы NSURLConnection, внутри NSOperation, которая, в свою очередь, управляется NSOperationQueue. Я делаю объект очереди в синглтоне, поэтому я просто получаю доступ к экземпляру из любого места и сообщаю ему, когда мне нужно начать новое соединение.

1
ответ дан 18 December 2019 в 06:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: