Хобрук: Ваш путь к мастерству в программировании

NSURLConnection запущен в другом потоке. Методы делегата не вызываются

Я запускаю NSURLConnection в другом потоке:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
        ^{
            NSURLConnection *connection = [NSURLConnection connectionWithRequest:[request preparedURLRequest] delegate:self];
            [connection start];
         });

Но мой метод делегата не вызывается:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)data;

При запуске в основном потоке все в порядке. Как я могу запустить соединение в другом потоке и получить методы делегата, вызываемые в том же потоке?


  • Roo, connectionWithRequest уже является асинхронным, вам не нужно использовать его dispatch_async. 21.08.2015
  • К вашему сведению, вы также запускаете это соединение дважды. Когда вы звоните connectionWithRequest, он уже устанавливает для вас соединение. Используйте start только при использовании опции startImmediately для FALSE. 21.08.2015

Ответы:


1

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

Если вы хотите получать обратный вызов в фоновом потоке, вы можете использовать метод setDelegateQueue или sendAsynchronousRequest:queue:completionHandler::

NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:request
                                                          delegate:self
                                                  startImmediately:NO];
[connection setDelegateQueue:[[NSOperationQueue alloc] init]];
[connection start];

Самый простой способ запустить NSURLConnection в фоновом потоке через GCD:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
               ^{
                   NSURLResponse* response = nil;
                   NSError* error = nil;
                   [NSURLConnection sendSynchronousRequest:request] returningResponse:&response error:&error];
                   NSLog(@"%@", response);
               });
24.08.2015

2

Да, это хорошо известное поведение NSURLConnection, потому что ему нужен цикл выполнения для обработки событий делегата. Наиболее распространенное решение: (а) создать его экземпляр с помощью initWithRequest:delegate:startImmediately:, где startImmediately равно FALSE; (b) вручную scheduleInRunLoop:forMode:, чтобы запланировать его в основном цикле выполнения; а затем (c) start соединение.

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

Кроме того, к вашему сведению, эффективная iOS9, NSURLConnection устарела, поэтому вам все равно следует использовать NSURLSession. И NSURLSession не страдает от этого ограничения.

21.08.2015

3

У меня была аналогичная проблема. Сейчас я запускаю запрос NSURLConnection в основном потоке — он выполняется асинхронно, поэтому не замедляет работу вашего приложения. В connectionDidFinishLoading я запускаю следующий код для обработки результатов моих вызовов. Я выполняю проверку, потому что у меня есть вызов NSURLConnection, который может инициировать другие сетевые вызовы. Поскольку они уже работают в фоновом потоке, я не хочу запускать новый.

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
   if ([NSThread isMainThread]) {
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
         //Background Thread
         [self processFinishLoading:connection];
      });
   }
   else {
      [self processFinishLoading:connection];
   }
}
22.08.2015
Новые материалы

Прогресс в технологии Трансформеров часть 3
Многомасштабный управляющий сигнальный преобразователь для бесфазного синтеза движения (arXiv) Автор: Линтао Ван , Кун Ху , Лей Бай , Юй Дин , Ваньли Оуян , Чжиюн Ван . Аннотация:..

Представляем поддержку компонентов Vue.js. Мгновенный HMR и многое другое.
Хотя у FuseBox уже был плагин Vue, он был базовым и не имел многих функций, которые делали работу с Vue.js такой приятной. Однако с этим выпуском мы рады сообщить, что в FuseBox..

Приключения в Javascript, часть 1
Я продолжаю думать о том, чтобы писать больше, но чем больше я думаю об этом, тем меньше я это делаю. Итак, сегодня я перестал думать и начал писать. Отсюда можно только спускаться… В..

Понимание дженериков в TypeScript: подробное руководство
Введение TypeScript, строго типизированный надмножество JavaScript, хорошо известен своей способностью улучшать масштабируемость, удобочитаемость и ремонтопригодность приложений. Одной из..

Учебные заметки JavaScript Object Oriented Labs
Вот моя седьмая неделя обучения программированию. После ruby ​​и его фреймворка rails я начал изучать самый популярный язык интерфейса — javascript. В отличие от ruby, javascript — это более..

Разбор строк запроса в vue.js
Иногда вам нужно получить данные из строк запроса, в этой статье показано, как это сделать. В жизни каждого дизайнера/разработчика наступает момент, когда им необходимо беспрепятственно..

Предсказание моей следующей любимой книги 📚 Благодаря данным Goodreads и машинному обучению 👨‍💻
«Если вы не любите читать, значит, вы не нашли нужную книгу». - J.K. Роулинг Эта статья сильно отличается от тех, к которым вы, возможно, привыкли . Мне очень понравилось поработать над..