Не удается вернуть фоновый сеанс URL-адреса

#ios #background #nsurlsession #nsurlsessionconfiguration

#iOS #фон #nsurlsession #nsurlsessionconfiguration

Вопрос:

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

Код для создания запроса довольно шаблонный:

 NSURLSessionConfiguration *sessionConfig =
[NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier];
sessionConfig.sessionSendsLaunchEvents = true;
sessionConfig.discretionary = false;
sessionConfig.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
sessionConfig.timeoutIntervalForResource = 60 * 60 * 24; //One day. Default is 7 days!

/* Create session, and optionally set a NSURLSessionDelegate. */
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig
                                                      delegate:self
                                                 delegateQueue:[NSOperationQueue mainQueue]];

NSURLComponents *urlComponents = [NSURLComponents new];
urlComponents.scheme           = @"https";
urlComponents.host             = @"jsonplaceholder.typicode.com";
urlComponents.path             = @"/posts/1";

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[urlComponents URL]];
request.HTTPMethod           = @"PUT";

NSLog(@"Making request: %@", request);

/* Start a new Task */
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
[task resume];
  

Но я никогда ничего не получаю обратно. У меня есть необходимые фоновые режимы (возможно)

       <key>UIBackgroundModes</key>
      <array>
              <string>fetch</string>
              <string>remote-notification</string>
      </array>
  

и мой делегат делегирует все

 <NSURLSessionDelegate, NSURLSessionDataDelegate,NSURLConnectionDataDelegate,NSURLConnectionDelegate,NSURLSessionTaskDelegate>
  

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

Репозиторий GitHub для BackgroundSender

Ответ №1:

В делегате приложения handleEventsForBackgroundURLSession вы ничего не делаете с обработчиком завершения. Вы должны:

  • сохраните копию completionHandler ;

  • запустите фоновый NSURLSession режим с этим идентификатором; и

  • по завершении обработки всех методов делегирования вызовите сохраненный обработчик завершения; мы часто делаем это URLSessionDidFinishEventsForBackgroundURLSession .


Кстати, вы не должны использовать задачи с данными с фоновыми сеансами. Обычно вам следует использовать задачу загрузки или выгрузки.


Кроме того, эти фоновые режимы не нужны для фона NSURLSession . Фоновая выборка предназначена для решения другой проблемы, а именно периодического опроса, чтобы узнать, есть ли на вашем сервере доступные данные. Если вам это нужно, то, во что бы то ни стало, используйте fetch фоновый режим, но поймите, что это отдельная тема от простого выполнения фоновых запросов.

См. раздел «Выборочная выборка небольших объемов содержимого» в руководстве по программированию приложений для iOS: фоновое выполнение для обсуждения фоновой выборки и сравните это с загрузкой содержимого в фоновом разделе.

Аналогично, remote-notification ключ тоже не связан. Как говорится в документах, remote-notification используется, когда «приложение хочет начать загрузку контента при поступлении push-уведомления. Используйте это уведомление, чтобы свести к минимуму задержку при отображении содержимого, связанного с push-уведомлением «.

Комментарии:

1. У handleEventsForBackgroundURLSession не было реализации, поскольку я никогда не видел, чтобы она вызывалась. Ваш комментарий о неиспользовании задач с данными, похоже, был проблемой — я изменил его на download task, просто чтобы посмотреть, сработает ли он, и сразу же получил вызов handleEventsForBackgroundURLSession . Ключ удаленного уведомления является артефактом из исходного проекта, но подумал, что он также может применяться к запуску задач, запускаемых локальными уведомлениями.

2. Очень хорошо. Кстати, обязательно вызовите этот обработчик завершения, переданный handleEventsForBackgroundURLSession , когда вы закончите обработку методов делегирования для завершенных запросов, иначе ОС убьет ваше приложение, а не изящно приостановит его, тем самым предотвращая другие фоновые процессы (например, удаленные уведомления и фоновую выборку).