Хорошая модель для интернет-запросов с Grand Central Dispatch?
В настоящее время я использую синхронный ASIHTTPRequest с очередями GCD для загрузки данных из Интернета, а затем проанализируйте данные ответа с помощью JSONKit. Что вы думаете об этой схеме. Заранее благодарю вас.
Вот мой код:
dispatch_async(queue, ^(void) {
// Request is ASIHTTPRequest.
[request startSynchronous];
// Parse JSON.
NSArray *array = [[request responseData] objectFromJSONDataWithParseOptions:JKParseOptionLooseUnicode];
// Callback on the main queue to update UI.
dispatch_async(dispatch_get_main_queue(), ^(void) {
callbackBlock(array);
});
});
EDIT: Причина, по которой я использую ASIHTTPRequest, заключается в том, что мне нужно изменить заголовок запроса для OAuth и использовать метод POST для загрузки изображений.
Ответы
Ответ 1
Итак, вы заменили это
- (void)doDownload {
NSURL *url = [NSURL URLWithString:@"http://foobar.com"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
connection = [[NSURLConnection alloc] initWithRequest:aURLRequest delegate:self];
receivedData = [[NSMutableData data] retain];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[_receivedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSArray *array = [_receivedData objectFromJSONDataWithParseOptions:JKParseOptionLooseUnicode];
callbackBlock(array);
}
с этим -
- (void)doDownload {
NSURL *url = [NSURL URLWithString:@"http://foobar.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^(void) {
[request startSynchronous];
NSArray *array = [[request responseData] objectFromJSONDataWithParseOptions:JKParseOptionLooseUnicode];
// Callback on the main queue to update UI.
dispatch_async(dispatch_get_main_queue(), ^(void) {
callbackBlock(array);
});
});
}
и 10 000 строк кода из ASIHTTPRequest.
Что у вас получилось?
NSURLConnection полностью асинхронный, использует GCD, кеши, автоматическую почтовую разметку и распаковку и т.д. и т.д.
По этой причине и, исходя из (возможно, неполной) информации, я бы сказал, что это был действительно ужасный фрагмент кода.
Конечно, контекст - это все - и у вас может быть действительно, действительно, действительно хорошая причина для переопределения уже существующей функциональности кода библиотеки, предоставленной Apple.
Ответ 2
В WWDC2010 для сетевого программирования Apple рекомендует использовать асинхронное программирование с помощью RunLoop.
- WWDC 2010 Session 207 - Сетевые приложения для iPhone OS, часть 1
- WWDC 2010 Session 208 - Сетевые приложения для iPhone OS, часть 2
Асинхронный запрос NSURLConnection является одним из наиболее эффективных способов. Но если вы хотите использовать ASIHTTPRequest, как насчет этого? (Асинхронный запрос ASIHTTPRequest реализован с использованием NSOperationQueue, он не такой же, как NSURLConnection асинхронный.)
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setCompletionBlock:^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSData *responseData = [request responseData];
/* Parse JSON, ... */
dispatch_async(dispatch_get_main_queue(), ^{
callbackBlock(array);
});
});
}];
[request setFailedBlock:^{
NSError *error = [request error];
/* error handling */
}];
[request startAsynchronous];
Ответ 3
Этот код выглядит нормально для одного сетевого подключения, но если вы используете ASIHTTPRequest, скорее всего, вы будете мобильным приложением. Для нескольких одновременных загрузок я бы выполнил очередь (см. "Использование очереди" в документах ASIHTTPRequest), где вы можете указать количество максимальных одновременных подключений (например, использовать 2 на GPRS и 8 на Wi-Fi) или уменьшить полосу пропускания. Затем в селекторе финиша используйте GDC или что-то еще, чтобы запустить обработку данных из основного потока пользовательского интерфейса.
В сущности, использование блоков с ASIHTTPRequest для простого случая приводит только к другому синтаксису в отношении NSURLConnection, как упоминалось в fakeAccount22. И NSURLConnection также имеет синхронные методы, поэтому вы можете избежать внешней зависимости (и потенциального источника ошибок/проблем) и использовать это в блоках.
Ответ 4
Лучший способ сделать это - использовать gcd при получении обратного вызова, а не при инициировании запроса. Затем вы можете анализировать фоновый поток и notifiy на основной теме. Удачи!