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)
- DataProvider запускает асинхронную передачу (старый подход watchOS 2, который предполагает, что он находится на переднем плане, а не на заднем плане).
- Этот фоновый поток (фоновой задачи, которая может или не может быть приостановлена, но еще не завершена) ожидает, что фоновая задача будет обрабатывать свое завершение после завершения асинхронной передачи.
- DataProvider запускает асинхронную передачу (старый подход watchOS 2, который предполагает, что он находится на переднем плане, а не на заднем плане).
Короче говоря, вы ожидали, что ваша задача фонового обновления будет ожидать в фоновом режиме асинхронной передачи. Это немного запутанно (поскольку задача обновления должна выполнять работу в фоновом режиме, а не ждать завершения другой работы).
Лучший способ для WatchOS 3:
Поскольку асинхронная передача может быть приостановлена, лучше использовать URLSession
фоновая передача.
Всегда загружайте и загружайте данные, используя фоновую передачу URLSession. Фоновые переносы происходят в отдельном процессе. Они продолжают передавать данные даже после завершения работы вашего приложения. Асинхронные загрузки и выгрузки, с другой стороны, приостановлены с вашим приложением. Учитывая короткое время работы приложений watchOS, вы не можете гарантировать, что асинхронная передача завершится до приостановки приложения.
Позволяя WKURLSessionRefreshBackgroundTask
В ответ на фоновую передачу ваше расширение может быть разбужено в фоновом режиме после завершения сеанса, передать данные этого сеанса поставщику данных, а затем обновить сложность.
Предложение о поставщике данных:
Кажется, что он несет ответственность как за передачу данных, так и за предоставление данных. Возможно, вы захотите разделить сетевую часть на отдельный компонент и просто позволить ему быть хранилищем данных.
У меня складывается впечатление, что это должен быть некий синглтон (за кадром), но вы инициализируете экземпляр как DataProvider()
,
С точки зрения читабельности, из предоставленного кода не очевидно, что источник данных усложнения будет использовать того же поставщика данных, что и тот, кто получил данные.
Вам следует избегать принудительного развертывания опций:
когда activeComplications
равно нулю (например, когда сложность была удалена с циферблата между последним обновлением и этим обновлением), ваш код будет некорректно зависать.
Вы должны использовать guard
или же if let
сначала проверить, что у вас все еще есть активное осложнение.