WKURLSessionRefreshBackgroundTask не вызывается при попытке обновления фона в watchOS

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

По предложению 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: Использование WKRefreshBackgroundTask для обновления приложений WatchKit в фоновом режиме.

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

Заранее спасибо за помощь!

2 ответа

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

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

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

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

пс. это работает в симуляторе (xcode 8.3.3, watchOS 3.2)

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

let backgroundSession = URLSession (конфигурация: backgroundSessionConfig, делегат: self, делегат Queue: nil)

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

WatchOS 3 WKApplicationRefreshBackgroundTask didReceiveChallenge

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

Другие вопросы по тегам