reloadTimeline() не обновляет усложнение

Я пытаюсь создать приложение для watchOS 3 и хочу обновить сложность в фоновом режиме.

Во-первых, я получаю новые данные с сервера в фоновом режиме в handle(), После этого я обновляю свои активные осложнения, звоня complicationServer.reloadTimeline(for:),

В консоли я вижу сообщение "ОБНОВЛЕНИЕ СЛОЖНОСТИ", поэтому код выполняется.

Тем не менее, после перезагрузки, сложность по- прежнему показывает старые данные. Если я переключаю циферблат и возвращаюсь назад, то осложнение иногда перезагружается. Должен ли я сделать что-то еще, чтобы перезагрузить сложность из фоновой задачи?

func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
    for task : WKRefreshBackgroundTask in backgroundTasks {
        if (WKExtension.shared().applicationState == .background) {
            if task is WKApplicationRefreshBackgroundTask {
                let dataProvider = DataProvider()
                dataProvider.getData(station: "Name", completion: { (data, error) in
                    self.updateComplication()
                    self.scheduleNextBackgroundRefresh()

                    task.setTaskCompleted()
                })
            }
        } else {
            task.setTaskCompleted()
        }
    }
}

func updateComplication() {
    let complicationServer = CLKComplicationServer.sharedInstance()

    for complication in complicationServer.activeComplications! {
        print("UPDATE COMPLICATION")
        complicationServer.reloadTimeline(for: complication)
    }
}

1 ответ

Решение

Ваш текущий подход:

У вас есть смесь watchOS 2 и watchOS 3.

  • WKApplicationRefreshBackgroundTask (новый подход к watchOS 3)
    1. DataProvider запускает асинхронную передачу (старый подход watchOS 2, который предполагает, что он находится на переднем плане, а не на заднем плане).
      • Этот фоновый поток (фоновой задачи, которая может или не может быть приостановлена, но еще не завершена) ожидает, что фоновая задача будет обрабатывать свое завершение после завершения асинхронной передачи.

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

Лучший способ для WatchOS 3:

Поскольку асинхронная передача может быть приостановлена, лучше использовать URLSession фоновая передача.

Всегда загружайте и загружайте данные, используя фоновую передачу URLSession. Фоновые переносы происходят в отдельном процессе. Они продолжают передавать данные даже после завершения работы вашего приложения. Асинхронные загрузки и выгрузки, с другой стороны, приостановлены с вашим приложением. Учитывая короткое время работы приложений watchOS, вы не можете гарантировать, что асинхронная передача завершится до приостановки приложения.

Позволяя WKURLSessionRefreshBackgroundTask В ответ на фоновую передачу ваше расширение может быть разбужено в фоновом режиме после завершения сеанса, передать данные этого сеанса поставщику данных, а затем обновить сложность.

Предложение о поставщике данных:

Кажется, что он несет ответственность как за передачу данных, так и за предоставление данных. Возможно, вы захотите разделить сетевую часть на отдельный компонент и просто позволить ему быть хранилищем данных.

У меня складывается впечатление, что это должен быть некий синглтон (за кадром), но вы инициализируете экземпляр как DataProvider(),

С точки зрения читабельности, из предоставленного кода не очевидно, что источник данных усложнения будет использовать того же поставщика данных, что и тот, кто получил данные.

Вам следует избегать принудительного развертывания опций:

когда activeComplications равно нулю (например, когда сложность была удалена с циферблата между последним обновлением и этим обновлением), ваш код будет некорректно зависать.

Вы должны использовать guard или же if let сначала проверить, что у вас все еще есть активное осложнение.

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