如何正确实现从 iOS 应用程序到 watchOS2 复杂功能的设置传输

How to correctly implement transfer of settings from iOS app to watchOS2 complication

我想要实现的是:

  1. 并发症在后台以 30 的间隔更新 分钟
  2. 只要手表应用程序运行并且 接收自己的更新数据
  3. 并发症随时更新 iOS 应用程序运行并且用户更改了影响 观察数据(例如改变天气观测的位置,或 显示单位)

第 1 项和第 2 项似乎很简单,并且在此处得到了很好的解决:

但是,对于第 3 项,在 iOS 应用程序中,我设置了一个 WCSession 实例并调用 transferCurrentComplicationUserInfo,将新设置作为 NSDictionary 发送。在手表扩展中,这会调用 WCSessionDelegate 中的 didReceiveUserInfo。

- (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary<NSString *,id> *)userInfo {
    // Code here to apply the new settings
    // ....
    // Invoke a NSUSRLSession-based web query to get new data
    [self queryForNewDataWithCompletionHandler:^(NCUpdateResult result) {
        if (result == NCUpdateResultNewData) {
            // Have new data from web to display
            CLKComplicationServer *server = [CLKComplicationServer sharedInstance];
            for (CLKComplication *complication in server.activeComplications) {
                [server reloadTimelineForComplication:complication];
            }
        }
        // Set date for next complication update to 30 mins from now
        // ...
    }];
}

我遇到的问题是 watchOS 在调用 didReceiveUserInfo 后不久在单独的线程中调用 requestedUpdateDidBegin 并且在我有机会使用新收到的 UserInfo 字典中的新设置获取更新数据之前开始执行应用程序。

因此,并发症会在短时间内连续更新两次 - 一次是由 WatchOS 调用 requestedUpdateDidBegin,它只是用现有(陈旧的)数据重新更新并发症,然后我很快就会从网络上收到新数据并且然后必须在我自己的代码中再次更新它们。

这似乎是不必要的,也是一种资源浪费,更不用说 Apple 允许的有限更新预算(据说每小时 2 次)。

我是不是做错了什么?在我有机会从网络获取新数据之前,如何防止 watchOS2 调用 requestedUpdateDidBegin?

transferCurrentComplicationUserInfo 的目的是立即将当前的并发症数据传递给扩展程序。在您的代码中,您正在传递设置,但是您不包括任何天气数据。

您看到的问题源于尝试异步在扩展中获取新数据(在数据可用之前返回)。

要处理此问题,您应该根据新设置在 phone 上获取当前天气数据,然后在当前复杂用户信息中传递(新设置以及)天气数据。

- (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary<NSString *,id> *)userInfo {
    // Code here to apply the new settings for future updates
    // ....
    // Code here to update cache/backing store with current weather data just passed to us
    // ....

    CLKComplicationServer *server = [CLKComplicationServer sharedInstance];
    for (CLKComplication *complication in server.activeComplications) {
        [server reloadTimelineForComplication:complication];
    }
}

这样,复杂功能服务器可以使用您刚刚传输到手表的当前复杂功能数据立即更新时间线。

没有陈旧的数据,没有不必要的第二次更新。