6

Я работаю над усложнением для получения запланированных данных из веб-службы. Каждые 20-30 минут (или вручную) я планирую WKRefreshBackgroundTask для этого.WKURLSessionRefreshBackgroundTask не вызывается при попытке сделать фоновое обновление в watchOS

Как явствует из Apple, я хочу, чтобы ОС обрабатывала выборку этих данных с помощью фона NSURLSession.

Это функция я использую, чтобы загрузить данные мне нужно:

func scheduleURLSession() 
{ 
    print("\nScheduling URL Session...") 

    let backgroundSessionConfig:URLSessionConfiguration = URLSessionConfiguration.background(withIdentifier: NSUUID().uuidString) 
    backgroundSessionConfig.sessionSendsLaunchEvents = true 

    let backgroundSession = URLSession(configuration: backgroundSessionConfig) 

    let downloadTask = backgroundSession.downloadTask(with: URL(string: "https://www.myserver.com/somedata")!) 
    downloadTask.resume() 
} 

Несколько вещей об этом:

  1. Это дозвонились, когда я планировать его. Я вижу его заявление на печать в консоли.
  2. Это почти идентично примеру Apple.
  3. Я пропустил URL-адрес. Тот же URL-адрес работает в приложениях iOS/watchOS просто отлично, поэтому с ним ничего не происходит.

Проблема в том, что я звоню resume() по задаче и позволяет ей разбудить мое приложение, когда оно будет завершено, и это тоже не похоже.

Когда он заканчивает, он должен возвращаться в обработчик WKExtensionDelegate:

func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) 

как WKURLSessionRefreshBackgroundTask, но это не так.

Мой код, идентичный образцу кода Apple, затем создает еще один сеанс, но присоединяется к нему через идентификатор WKURLSessionRefreshBackgroundTask. Здесь задан делегат для обработки загруженных данных. Проверьте код:

func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) { 
    for task in backgroundTasks { 
     switch task { 

     case let backgroundTask as WKApplicationRefreshBackgroundTask: 
      print("\nWatchKit - WKApplicationRefreshBackgroundTask") 
      // self.updateComplicationDataArrivalTimes(backgroundTask) 
      self.scheduleURLSession() 
      backgroundTask.setTaskCompleted() 

     case let snapshotTask as WKSnapshotRefreshBackgroundTask: 
      // Snapshot tasks have a unique completion call, make sure to set your expiration date 
      print("\nWatchKit - WKSnapshotRefreshBackgroundTask") 
      snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil) 

     case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask: 
      print("\nWatchKit - WKWatchConnectivityRefreshBackgroundTask") 
      connectivityTask.setTaskCompleted() 

     case let urlSessionTask as WKURLSessionRefreshBackgroundTask: 
      print("\nWatchKit - WKURLSessionRefreshBackgroundTask") 
      let backgroundConfigObject = URLSessionConfiguration.background(withIdentifier: urlSessionTask.sessionIdentifier) 
      let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: self, delegateQueue: nil) 

      print("Rejoining session ", backgroundSession) 
      urlSessionTask.setTaskCompleted() 

     default: 
      // make sure to complete unhandled task types 
      task.setTaskCompleted() 
     } 
    } 
} 

Но опять же, похоже, он никогда не возвращаться. Я не могу понять, почему это работает, несмотря на то, что код идентичен образцу кода Apple для этого проекта: WatchBackgroundRefresh: Using WKRefreshBackgroundTask to update WatchKit apps in the background.

Есть ли какие-то настройки в моем проекте, которые мне не хватает? Я помещаю весь этот код в ExtensionDelegate, новый в watchOS 3. Я также согласен с WKExtensionDelegate и URLSessionDownloadDelegate.

Спасибо за вашу помощь заранее!

+0

Вы когда-нибудь решали это? –

+1

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

+0

Спасибо! То .... хорошо, страшные новости. Но это также объясняет, почему я не могу получить пример Яблок, работающий в симуляторе. Я не владею Apple Watch, так что либо я покупаю одно, либо убираю приложение :( –

ответ

3

Я никогда не получал пример от Apple, но я действительно работал в фоновом режиме. В отличие от их примера вам нужно будет сделать себя делегатом сессии. Так создать свой фоновый сеанс, как это вместо:

пусть backgroundSession = URLSession (конфигурация: backgroundSessionConfig, делегат: Я, delegateQueue: ноль)

У меня есть подробный пример кода здесь (см код на вопрос в):

WatchOS 3 WKApplicationRefreshBackgroundTask didReceiveChallenge

Надеюсь, что это поможет.

+0

Я не вижу, как это отличается от того, что вы опубликовали в вопросе. –

+0

Код вопроса работает в производстве. – CodenameDuchess

4

У меня это работает! Я начал много смотреть на видеозаписи/примечания WWDC'16, сравнивая их с примером из Apple WatchBackgroundRefresh.Затем, просматривая форумы Apple Dev, я нашел this thread с той же проблемой, с которой мы столкнулись. Там, парень, «Daniel Fontes» публикует свой «рецепт», чтобы заставить его работать (обратите внимание, а не на принятый ответ!), И это в сочетании с видео работало для меня.

Что я сделал, чтобы сделать пример работы Apple:

  1. Сделать MainInterfaceController URLSessionDelegate
  2. Создайте локальную переменную: var savedTask:WKRefreshBackgroundTask?
  3. В функции handle(backgroundTasks:) сохраните WKURLSessionRefreshBackgroundTask локальной переменной self.savedTask = task - не task.setTaskCompleted() (!)
  4. В urlSession - didFinishDownloading: установите сохраненную задачу в законченное состояние: self.savedTask?.setTaskCompleted() после того, d полученные данные.
  5. Убедитесь, что ресурс, к которому вы обращаетесь, - https: //, в противном случае добавьте «Параметры безопасности транспорта приложения» в файл Info.plist.

Надеюсь, это поможет!

ps. это работает в simnulator (xcode 8.3.3, watchOS 3.2)

+0

Отличный совет @ Jens Peter !! IT наконец-то поманил! Моя ошибка заключалась в том, что я использовал другой класс для делегата Но теперь делегаты находятся на моем ExtensionDelegate, и это работает. Но две вещи, которые я не могу решить: 1 - Я продолжаю получать это сообщение, что фоновый сеанс с используемым идентификатором уже существует. Меня это беспокоит, но все работает во всяком случае. 2 - где вы помещаете вызов 'invalidateAndCancel()'? Я не использую его. Нужно ли мне? – francisaugusto

Смежные вопросы