Хороший шаблон для интернет-запросов с Grand Central Dispatch? - PullRequest
12 голосов
/ 06 июля 2011

В настоящее время я использую синхронный запрос 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);
        });
    });

РЕДАКТИРОВАТЬ: причина, по которой я использую ASIHTTPRequest, заключается в том, что мне нужно изменить заголовок запроса для OAuth и использовать метод POST для загрузки изображений.

Ответы [ 4 ]

12 голосов
/ 06 июля 2011

Таким образом, вы заменили

- (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);
        });
    });
}

и 10000 + строк кода из ASIHTTPRequest .

Чтоу вас это получилось?

NSURLConnection полностью асинхронный, использует GCD, кеши, автоматическое zip / unzip и т. д. и т. д.

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

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

2 голосов
/ 07 июля 2011

На WWDC2010 для сетевого программирования Apple рекомендует использовать асинхронное программирование с RunLoop.

  • WWDC 2010, сессия 207 - Сетевые приложения для iPhone OS, часть 1
  • WWDC 2010, сессия 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];
0 голосов
/ 30 ноября 2011

Лучший способ сделать это - использовать gcd при получении обратного вызова, а не при инициировании запроса.Затем вы можете разобрать в фоновом потоке и уведомить о главном потоке.Удачи!

0 голосов
/ 22 июля 2011

Этот код выглядит нормально для одного сетевого подключения, но если вы используете ASIHTTPRequest, вы, вероятно, будете мобильным приложением.Для нескольких одновременных загрузок я бы реализовал очередь (см. «Использование очереди» в документации ASIHTTPRequest), где вы можете указать максимальное количество одновременных подключений (например, использовать 2 на GPRS и 8 на wifi) или уменьшить пропускную способность.Затем в окончательном селекторе используйте GDC или что-то еще для запуска обработки данных из основного потока пользовательского интерфейса.

По сути, использование блоков с ASIHTTPRequest для простого случая приносит вам только другой синтаксис в отношениик NSURLConnection, как упоминалось в fakeAccount22.И NSURLConnection также имеет синхронные методы, поэтому вы можете избежать внешней зависимости (и потенциального источника ошибок / проблем) и использовать ее в блоках.

...