Блокирует ли NSURLConnection основной поток / поток пользовательского интерфейса - PullRequest
6 голосов
/ 13 июля 2010

Я загружаю изображения в ячейки табличного представления, когда они прокручиваются на экран. По причинам UX я начинаю загружать изображения в - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath. Я не жду, пока просмотр таблицы не закончится прокруткой. Когда ячейка табличного представления установлена, я начинаю загружать изображения, которых у меня уже нет. Однако они не загружаются полностью, пока табличное представление не перестанет двигаться. Как только он перестает двигаться, изображения практически мгновенно загружаются.

Есть ли способ использовать NSURLConnection, если он не заблокирован основным потоком пользовательского интерфейса? Или есть способ, которым эти изображения будут загружаться очень быстро во время прокрутки табличного представления.

** РЕДАКТИРОВАТЬ **

Чтобы доказать, что NSURLConnection медленнее, я использовал NSThread, чтобы отсоединить новый селектор в другом потоке. Затем я загружаю данные и перезваниваю в главный поток, где создаю UIImage и показываю его в табличном представлении. Этот метод работает НАМНОГО быстрее.

Лично я думаю, что NSURLConnection попадает в цикл обработки событий, когда прокрутка UITableView блокирует его.

Ответы [ 4 ]

22 голосов
/ 13 марта 2012

Чтение NSDefaultRunLoopMode против NSRunLoopCommonModes для хорошего объяснения того, почему все уведомления делегата загрузки поставлены в очередь, но загрузка при прокрутке при использовании основного потока изменяется с:

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
                                                              delegate:self];

к этому:

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
                                                              delegate:self
                                                      startImmediately:NO];
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop]
                      forMode:NSRunLoopCommonModes];
[connection start];
2 голосов
/ 13 июля 2010

Я уже сталкивался с этой проблемой раньше. Методы асинхронного делегата NSURLConnection не запускаются во время прокрутки scrollView. Хотя загрузка работает в фоновом режиме, ваш главный поток не информируется о новых изображениях. Как и вы, я считаю, что проблема связана с прокруткой прокрутки во внутреннем NSRunLoop с другим RunLoopMode. Я говорил об этом с сотрудниками Apple, чтобы они посмотрели мой код, но мы не смогли найти решение.

С другой стороны, у Джеффа Ламарша есть это сообщение в его блоге, где он делает то же самое, и это работает, как и ожидалось. Я не смог понять, что он делает по-другому (в основном из-за нехватки времени), но это может стоить посмотреть.

1 голос
/ 13 июля 2010

Если вы имеете в виду «NSURLConnection выполняется в главном потоке?», То да, я думаю, что это так. Соединение открывается, и методы делегата выполняются в главном потоке. Я не нашел никакой документации, которая могла бы предложить другое, и вы можете проверить это, отладив.

Я думаю, что ваше предположение, что прокрутка UITableView блокирует обратные вызовы NSURLConnection в главном цикле выполнения, верна.

Вы уже опубликовали одно решение, порождая тему для вашего селектора. Другой альтернативой может быть загрузка ваших файлов в виде NSOperations, что имеет несколько преимуществ:

  • Если вы заставляете операции выполняться одновременно (см. Отличный пост Дэйва Дрибина на этом ), вы можете ограничить количество одновременных загрузок, что может быть желательно, если у вас очень большое количество изображений в твой стол. Вы говорите, что ваши загрузки происходят «почти мгновенно», но это может быть не так, если у вашего пользователя медленное соединение и ваша таблица содержит много изображений.
  • Вы можете отменить все операции, если пользователь делает что-то, что делает загрузку изображения неактуальной, например, выполняет другой поиск.

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

0 голосов
/ 13 июля 2010

Звучит так, как будто вы делаете синхронную загрузку.

http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html#//apple_ref/doc/uid/20001836-170129

Прочитайте и убедитесь, что вы используете асинхронные API

...