reloadTimeline() 不更新并发症

reloadTimeline() doesn't update complication

我正在尝试制作一个 watchOS 3 应用程序,我想在后台任务中更新我的复杂功能。

首先,我在 handle() 的后台任务中从服务器获取新数据。之后,我通过调用 complicationServer.reloadTimeline(for:).

来更新我的活动并发症

在控制台中我确实看到消息 "UPDATE COMPLICATION," 所以代码被执行了。

但重新加载后,并发症仍然显示旧数据。如果我切换表盘然后再切换回来,那么复杂功能有时会重新加载。我是否必须执行其他操作才能从后台任务重新加载复杂功能?

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)
    }
}

您目前的做法:

您混合了 watchOS 2 和 watchOS 3 方法。

  • WKApplicationRefreshBackgroundTask(新的 watchOS 3 方法)
    1. DataProvider 开始异步传输(旧的 watchOS 2 方法假定它在前台,而不是在后台)。
      • 一旦异步传输完成,该后台线程(可能会或可能不会暂停但尚未完成的后台任务)期望让后台任务处理其完成。

简而言之,您希望后台刷新任务在后台等待异步传输。这有点令人费解(因为刷新任务应该是在后台工作,而不是等待其他工作完成)。

watchOS 3 更好的方法:

由于可以暂停异步传输,因此最好使用 URLSession 后台传输。

Always upload and download data using an URLSession background transfer. Background transfers occur in a separate process. They continue to transfer the data even after your app has terminated. Asynchronous uploads and downloads, on the other hand, are suspended with your app. Given the short run time of watchOS apps, you cannot guarantee that an asynchronous transfer will finish before the app is suspended.

通过让 WKURLSessionRefreshBackgroundTask 响应后台传输,您的扩展程序可以在后台唤醒 一旦会话完成 ,将该会话的数据传递给数据提供商,然后更新并发症。

关于数据提供者的建议:

似乎既有传递数据的责任,也有提供数据的责任。您可能需要考虑将网络部分拆分成一个单独的组件,并简单地让它成为一个数据存储库。

我的印象是它应该是某种单例(在幕后),但您将实例初始化为 DataProvider()

从可读性的角度来看,从提供的代码中看不出复杂数据源将使用与接收数据的数据提供者相同的数据提供者。

你应该避免强制解包选项:

activeComplications 为 nil 时(例如在上次更新和本次更新之间从表盘上删除了复杂功能),您的代码将无礼地崩溃。

您应该使用 guardif let 首先检查您是否仍有活动并发症。