Сбой запросов GCD на iOS 4 - PullRequest
       28

Сбой запросов GCD на iOS 4

2 голосов
/ 23 марта 2012

В моем приложении есть следующий код для загрузки некоторых данных из моего API. Он отлично работает, на самом деле замечательно в iOS 5, но в iOS 4 я получаю очень много ответов со статусом 204.

Это происходит только в iOS 4, это можно было бы рассматривать как ошибку API, но она прекрасно работает в браузере, в Rested.app, в iOS 5 и т. Д. ... только iOS 4 не работает, она не работает в симуляторе и на устройстве (iPhone 4).

Я вызываю этот код каждый раз, когда загружаю ячейку в табличное представление. У меня есть основной объект данных с состоянием загрузки, изначально установленным в no, если он не загружен, я выполняю этот код, если он загружен, я пропускаю этот код. В то же время я отображаю счетчик внутри ячейки в табличном представлении.

Я уверен, что это проблема с несколькими запросами в GCD на iOS 4.

Может кто-нибудь заметить что-то не так с моим фрагментом кода?

-(void)myFunction{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // query users participations (Network)

        NSError * _urlError = nil;
        NSString * url = [NSString stringWithFormat:@"my api url"];
        NSMutableURLRequest * loginHTTPRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
        [loginHTTPRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"];

        NSLog(@"Description: %@", [loginHTTPRequest description]);

        NSHTTPURLResponse   * _responseHeaders  = nil;
        NSData              * responseData      = [NSURLConnection sendSynchronousRequest:loginHTTPRequest 
                                                                        returningResponse:&_responseHeaders 
                                                                                    error:&_urlError];
        if(_urlError != nil){
            dispatch_async( dispatch_get_main_queue(), ^{
                // alert network connection error
            });
            return;
        }

        NSString *json_string = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];

        SBJsonParser *parser = [[SBJsonParser alloc] init];
        NSDictionary * jsonData = [NSDictionary dictionaryWithDictionary:[parser objectWithString:json_string]];
        [json_string release];
        [parser release];

        dispatch_async( dispatch_get_main_queue(), ^{
            // here [_responseHeaders statusCode] keeps returning 204 and there is nothing in responseData

            // do some Core Data stuff
        });

    });
}

UPDATE

Обратите внимание, что этот код работает нормально, если вызывается даже с циклом for, проблема заключается в том, что я вызываю этот метод из tableView: cellForRowAtIndexPath:

У меня есть объекты Core Data со свойством "isLoaded", установленным в NO и замененным на YES при удаленной загрузке. Когда источник данных моего табличного представления загружает ячейки для каждого объекта, tableView: cellForRowAtIndexPath: метод вызывает эту функцию, если свойство объекта isLoaded имеет значение NO.

Я подозревал, что проблема может быть в том, что при загрузке и перезагрузке таблицы происходит 2 или более одновременных вызова API. Каждая успешная загрузка из API вызывает reloadData для этого табличного представления.

Это позволяет мне иметь предварительно заполненное табличное представление со счетчиками и асинхронно загружать мои данные, когда мне это нужно, на экране, что приятно, потому что я могу эффективно использовать NSFetchedResultsController с ленивой загрузкой данных ядра моих объектов.

(у меня есть конечная точка для всех моих объектов, возвращающих массив идентификаторов объектов - я создаю объекты Core Data только с идентификаторами, все остальные данные, имя, дата и т. Д. И т. Д. Не загружаются до тех пор, пока они не понадобятся).

Когда я начинаю прокручивать новые ячейки, которые создаются / используются повторно, вызывают этот метод, и они всегда получают ответ 200 с данными. это только первая загрузка, которая вызывает этот «блок».

Ответы [ 2 ]

1 голос
/ 30 марта 2012

Мне кажется, я обнаружил проблему, я выполнял синхронные запросы в асинхронном потоке GCD, и по какой-то причине происходили тайм-ауты, но только для запросов в iOS 4, возможно, заголовки отправляются немного иначе, чем в iOS 4, что вызываетAPI, чтобы занять больше времени, чтобы ответить?Или, может быть, несколько (как в миллисекундах) запросов, отправленных из разных потоков синхронно в асинхронном потоке, конфликтовали в системе перед отправкой?

Как бы то ни было ... это не похоже на случай вызоваgoogle.com или даже мой собственный частный сервер, так что это должно быть как-то связано с заголовками и несколькими запросами ...

Я использую asi http из github, и он работает намного эффективнее, теперь яне использует GCD для этих запросов, просто очередь ASI.

Заключительные мысли о синхронных запросах iOS 4, выполняемых в асинхронном потоке GCD с возможными таймаутами, которые не соблюдаются, и возвращаются рано с состоянием 204?

0 голосов
/ 23 марта 2012

Хорошо - если это https, то вы, вероятно, не можете избежать использования sendSynchronousRequest.В документации говорится, что такие вещи, как [NSURLConnection connection:didReceiveAuthenticationChallenge:], не будут вызывать некоторые ключевые вещи, а именно:

Если для загрузки запроса требуется аутентификация, необходимо указать необходимые учетные данные как часть URL,Если аутентификация не удалась или учетные данные отсутствуют, соединение попытается продолжить без учетных данных.

Я все еще удивлен, что он работает на iOS5, если честно.Я думаю, вам придется использовать асинхронные методы, чтобы хотя бы отладить его, чтобы выяснить, что происходит.

...