NSURLConnection - как ждать завершения - PullRequest
1 голос
/ 05 мая 2009

Код нашего приложения для iPhone в настоящее время использует NSURLConnection sendSynchronousRequest, и это прекрасно работает, за исключением того, что нам нужно больше видеть ход соединения и кэширование, поэтому мы переходим к асинхронному NSURLConnection.

Какой самый простой способ дождаться завершения асинхронного кода? Оберните его в NSOperation / NSOperationQueue, executeSelector ... или как?

Спасибо.

Ответы [ 4 ]

4 голосов
/ 05 мая 2009

Я отвечаю на это, если кто-то еще столкнется с проблемой в будущем. Пример кода Apple URLCache является прекрасным примером того, как это делается. Вы можете найти его по адресу:

Как отмечает Джон в комментарии выше - не блокировать / ждать - уведомить.

2 голосов
/ 11 марта 2014

Я столкнулся с этим, потому что наше приложение использовало NSURLConnection sendSynchronousRequest во многих местах, где это имело смысл, например, когда некоторая обработка происходила в фоновом потоке, иногда требуя дополнительных данных для завершения обработки. Как то так:

// do some processing
NSData * data = someCachedData;
if (data = nil) {
    data = [NSURLConnection sendSynchronousRequest....]
    someCachedData = data;
}
// Use data for further processing

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

В какой-то момент нам понадобился делегат для наших подключений (для закрепления SSL-сертификата), и я стал троллить Интернет для поиска решений, и все было в форме: «просто используйте async и не боритесь с платформой! ». Ну, sendSynchronousRequest существует по причине, вот как воспроизвести его с базовым асинхронным соединением:

 + (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse *__autoreleasing *)response error:(NSError *__autoreleasing *)error
 {
     static NSOperationQueue * requestsQueue;
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
         requestsQueue = [[NSOperationQueue alloc] init];
         requestsQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount;
     });

     NSCondition * waitLock = [NSCondition new];
     [waitLock lock];

     __block NSError * returnedError;
     __block NSURLResponse * returnedResponse;
     __block NSData * returnedData;
     __block BOOL done = NO;
     [NSURLConnection sendAsynchronousRequest:request
                                        queue:requestsQueue
                            completionHandler:^(NSURLResponse * response, NSData * data, NSError * connectionError){

                     returnedError = connectionError;
                     returnedResponse = response;
                     returnedData = data;
                     [waitLock lock];
                     done = YES;
                     [waitLock signal];
                     [waitLock unlock];
                 }];
     if (!done) {
         [waitLock wait];
     }
     [waitLock unlock];
     *response = returnedResponse;
     *error = returnedError;
     return returnedData;
 }

Опубликовано здесь на случай, если кто-нибудь придет посмотреть, как я.

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

2 голосов
/ 06 мая 2009

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

Действительно, если вы заблокировали поток, соединение никогда не будет никуда идти, так как оно работает в том же потоке (да, даже если вы используете методы асинхронности).

2 голосов
/ 05 мая 2009

Чтобы использовать NSURLConnection в асинхронном режиме, вы предоставляете делегата при его инициализации в initWithRequest: Delegate :. Делегат должен реализовать методы делегата NSURLConnection. Обработка NSURLConnection выполняется в другом потоке, но методы делегата вызываются в потоке, который запустил асинхронную операцию загрузки для связанного объекта NSURLConnection.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...