NSURLConnection с NSRunLoopCommonModes

Я написал собственную реализацию HTTPClient для своего iOS-приложения, чтобы асинхронно загружать содержимое указанного URL-адреса. HTTPClient использует NSOperationQueue для постановки в очередь запросов NSURLConnection. Я выбрал NSOperationQueue, потому что хотел отменить любой или все текущие NSURLConnection в любой момент времени.

Я тщательно изучил, как реализовать свой HTTPClient, и у меня было два варианта выполнения NSURLConnection:

1) Выполнение каждого поставленного в очередь NSURLConnection в отдельном вторичном потоке.NSOperationQueue выполняет каждую поставленную в очередь операцию во вторичном потоке в фоновом режиме, и, следовательно, мне не нужно было делать что-либо явно для порождения вторичных потоков, кроме запуска моего NSURLConnection в переопределенном методе запуска подкласса NSOperation и запуска цикла выполнения для порожденного вторичного потока до тех пор, пока не будет connectionDidFinishLoading или вызывается connectionDidFailWithError. Это выглядит следующим образом:

if (self.connection != nil) {
            do {
                [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                                         beforeDate:[NSDate distantFuture]];
            } while (!self.isFinished);
}

2) Выполнение каждого поставленного в очередь NSURLConnection в основном потоке. Для этого внутри метода запуска я использовал PerformSelectorOnMainThread и снова вызывал метод запуска в основном потоке. При таком подходе я планировал NSURLConnection с NSRunLoopCommonModes, как показано ниже:

[self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

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

У меня сложилось впечатление, что я все еще работаю параллельно со вторым подходом, планируя NSURLConnection с помощью NSRunLoopCommonModes.Другими словами, с этим подходом я думал, что использую NSRunLoopCommonModes вместо многопоточности для параллелизма, так что наблюдатели для NSURLConnection будут вызывать либо connectionDidFinishLaunching, либо connectionDidFailWithError, как только это будет возможно, независимо от того, что основной поток делает с пользовательским интерфейсом в этот момент. время.

К сожалению, все мое понимание оказалось ошибочным, когда сегодня утром один из моих коллег показал мне, что с текущей реализацией NSURLConnection не возвращается до тех пор, пока представление прокрутки на одном из контроллеров представления не прекратит прокрутку. NSURLRequest для получения данных запускается, когда представление прокрутки вот-вот перестанет прокручиваться, но даже если оно было завершено до того, как представление прокрутки перестанет вызывать, каким-то образом NSURLConnection не вызывает обратно ни connectionDidFinishLoading, ни connectionDidFailWithError, пока представление прокрутки не прекратит прокрутку полностью. Это означает, что вся идея планирования NSURLConnection с NSRunLoopCommonModes в основном потоке для получения реального параллелизма с операциями пользовательского интерфейса (касания/прокрутка) оказалась ошибочной, и NSURLConnection все еще ждет, пока основной поток не будет занят прокруткой представления прокрутки.

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

Я действительно не хочу использовать первый подход, потому что это дорого из-за многопоточности.

Может ли кто-нибудь сообщить мне, если я неправильно понимаю второй подход? Если это правильно, что может быть причиной того, что планирование NSURLConnection с NSRunLoopCommonModes не работает должным образом?

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

6
задан indiantroy 12 April 2012 в 22:46
поделиться