Подтвердить что ты не робот

Хорошая модель для интернет-запросов с 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 для загрузки изображений.

4b9b3361

Ответ 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 на основной теме. Удачи!