Обработка потока с NSURLSessionDataTask - PullRequest
2 голосов
/ 06 октября 2019

Короче говоря, я пытаюсь отобразить данные из общедоступного файла JSON на веб-сайте. Процесс следующий:

Я запускаю загрузку с NSURLSessionDataTask, затем анализирую и отображаю JSON или обрабатываю ошибки, если они возникают. Вот мой соответствующий код:

- (void) initiateDownload {
    NSURLSessionConfiguration *sessionConfig    = [NSURLSessionConfiguration defaultSessionConfiguration];
    sessionConfig.timeoutIntervalForRequest     = 5.0f;
    sessionConfig.timeoutIntervalForResource    = 20.0f;

    NSURLSessionDataTask *downloadWeatherTask   = [urlSession dataTaskWithRequest:urlRequest
                                            completionHandler:^(NSData *data, NSURLResponse *response, NSError *downloadError) {
                                                if (downloadError) {
    dispatch_sync(dispatch_get_main_queue(), ^{
                                                        [self errorReceived:downloadError];
                                                        });
                                                } else if (data) {
    dispatch_sync(dispatch_get_main_queue(), ^{
                                                        [self parseWeatherJSON:data];
                                                        });
                                                }
                                            }];

    [downloadWeatherTask resume];
}

У меня есть пара вопросов по этому поводу:

  1. Я не так уж хорошо знаком с обработкой потоков. Хотя я добавил

    dispatch_sync(dispatch_get_main_queue(), ...)
    

    к обоим блокам завершения, и, похоже, он работает, я не уверен, что это лучший способ обеспечения безопасности потоков (раньше я получал все виды сообщений об ошибках и отображалданные заняли 10 секунд после окончания загрузки). Есть ли лучший способ обработать загрузку, а темы или мои сообщения являются приемлемым решением?

  2. Я бы хотел, чтобы пользователь мог запускать процесс загрузки вручную в любое время, когда он / онахочет обновить отображаемые данные. Сначала я один раз инициализировал NSURLSessionDataTask и сделал его доступным в любом месте класса;так что я могу просто вызывать резюме каждый раз, когда вызывается обновление. Тем не менее, я не смог найти команду, чтобы заново сделать процесс загрузки. После того, как я позвонил [downloadWeatherTask resume], я не смог запустить задачу с самого начала.

    Итак, я добавил задачу в отдельную функцию (ту, которую вы видите выше) и инициализировал ее там каждый раз, когда функцияназывается. Это прекрасно работает, но я не уверен, что это лучший способ. Например, безопасна ли память или я создаю новое задание каждый раз, когда пользователь инициирует вызов обновления и в конечном итоге ему не хватает памяти?

Спасибо за ответы!

Немного больше информации: я использую последнюю версию XCode 11 и целевую iOS 9 и выше.

1 Ответ

2 голосов
/ 06 октября 2019

NSURLSession по умолчанию будет использовать выделенную фоновую последовательную очередь для блоков завершения (и методов делегирования, если вы это сделаете). Но вы действительно хотите убедиться, что вы запускаете обновления пользовательского интерфейса из основной очереди (извлекается через dispatch_get_main_queue()). И, как правило, вы хотите избежать обновления свойств и иваров из нескольких потоков (если только они не имеют встроенной безопасности потоков, что является необычным), поэтому отправка обновлений этих свойств / иваров обратно в основную очередь довольно проста. способ достижения безопасности потока.

Итак, суть в том, что вы здесь делаете, хорошо.

Однако я не смог найти команду для повторного выполнения процесса загрузки. .

Вы выполняете (resume) заданную задачу только один раз. Если вы хотите выполнить аналогичный запрос еще раз, создайте новый экземпляр NSURLSessionDataTask.

...