何时何地获取Watch Complication的数据
在处理了几天的复杂问题之后,我有信心对以下更新过程进行如下说明:
- 系统调用
requestedUpdateDidBegin()
- 这是您可以确定您的数据是否已经改变的地方。 如果没有,你的应用程序不必做任何事情。 如果你的数据发生了变化,你需要调用:
- 如果所有数据都需要重置,则
reloadTimelineForComplication
。 -
extendTimelineForComplication
如果您只需要将新项目添加到并发症时间线的末尾。
- 如果所有数据都需要重置,则
- 注意:如果你在一天中花费了太多复杂的时间预算,系统实际上可能会调用
requestedUpdateBudgetExhausted()
而不是requestedUpdateDidBegin()
。 这是这个问题的原因。
- 这是您可以确定您的数据是否已经改变的地方。 如果没有,你的应用程序不必做任何事情。 如果你的数据发生了变化,你需要调用:
- 如果您调用了
reloadTimelineForComplication
,系统将调用getCurrentTimelineEntryForComplication
(以及取决于您的时间旅行设置的将来和过去的变体) - 这是猜测,因为我还没有testing过,但我相信,如果你调用
extendTimelineForComplication
,只有getTimelineEntriesForComplication(... afterDate date: NSDate ...)
将被调用。 - 然后系统会调用
getNextRequestedUpdateDateWithHandler
这样你可以指定多长时间,直到你的并发症需要一个新的更新。
苹果的文档很清楚,你不应该要求更新太频繁,或在复杂的代码中进行太多的处理,否则你将耗尽你的时间预算,你的复杂化将停止更新。 所以,我的问题是:何时何地进行更新?
对于上下文,我的情况是一个URL,返回数据每小时更改两次。
URL提取代码最明显的位置是func requestedUpdateDidBegin()
获取数据并存储,如果没有改变,就返回。 如果有变化,则延长或重新加载时间表。
但是,url提取可能代价高昂。 备择scheme:
- 将代码放在电话应用程序中,并通过
WCSession
发送,但是如果用户closures了该应用程序,那么更新将不再发生。 - 使用推送更新,但这不是一个Web应用程序,所以我没有地方发送它们。
- 显然,当用户与手表应用程序交互时,我会更新所有的数据,但是现在意味着只有在用户使用应用程序时才会更新,这不需要复杂的操作。
还有其他地方吗? 我可以在手表应用程序中有一个周期性的function,而不是复杂的一部分? 哪里是获取并发症更新数据的正确位置?
对于watchOS 3,Applebuild议您从使用复杂数据源getNextRequestedUpdateDate
预定更新切换来更新复杂function。
旧的方式为watchOS 2
requestedUpdateDidBegin()
实际上只是为了更新复杂性而devise的。 保持你的复杂性(和观看应用程序)是最新的通常涉及远远超过重新加载时间表(和asynchronous检索数据从来不适应旧的方法)。
watchOS的新途径3
新的更好的方法是使用后台刷新应用程序的任务 。 您可以使用一系列后台任务来安排和处理您在后台被唤醒的应用扩展程序,以便:
-
获取新的数据
- 使用WKWatchConnectivityRefreshBackgroundTask从手机获取数据,或者
- 使用WKURLSessionRefreshBackgroundTask从服务器下载数据
- 数据到达后更新模型,
- 从模型更新你的复杂(通过重新加载或延长时间轴),最后
- 更新您的应用的docker快照以显示docker上的数据
一旦任务完成,立即调用每个任务的setTaskCompleted
方法。
使用应用程序任务的其他好处
这种devise的关键特点之一是,手表扩展现在可以处理各种前景和背景的情况,其中包括:
- 最初在您的应用程序/并发症开始时加载数据,
- 在后台更新数据,当扩展被后台任务唤醒时,以及
- 当用户从docker恢复您的应用程序时,在前台更新数据。
无论您的应用程序位于前台还是后台 ,Apple都build议您使用每个机会,以使复杂function,应用程序和docker快照保持最新状态。
有什么限制吗?
每天可用任务总数除以docker中的应用数量。 docker中的应用程序越less,应用程序可以使用的任务就越多。 docker中的应用程序越多,可以使用的越less。
-
如果您的复杂function是活动的,您的应用程序可以每小时至less唤醒四次。
-
如果您的复杂function不活跃,您的应用程序将保证每小时至less唤醒一次。
由于您的应用程序现在正在后台运行,因此您需要高效快速地完成后台任务。
后台任务受CPU时间和CPU使用率的限制。 如果超过CPU时间(或在后台使用超过10%的CPU),系统将终止您的应用程序(导致崩溃)。
了解更多信息
-
“ devise优秀的Apple Watch体验”介绍了一个很好的介绍,解释何时以及为什么更新Watch应用程序。
-
具体来说, 保持您的手表应用程序最新的会议涵盖了所有你需要知道的复杂function,应用程序和docker快照保持最新。
-
WatchBackgroundRefresh示例代码演示了如何使用
WKRefreshBackgroundTask
在后台更新WatchKit应用程序。
编辑:茶(op)已经发布了一个很好的答案在https://stackoverflow.com/a/32994055/630614
这是一个有趣的问题,我一直在想很多相同的东西!
大多数情况下,当我正在处理新的并发症时,我需要退后一步,看看我什么时候需要更新它。 当“结束date”被设置时,“倒计时”复杂function可以一次设置所有未来的时间线条目。 显示Web服务当前状态的应用程序可能会在APNS通过时将相关数据存储在NSUserDefaults
。
如果您无法访问APNS,不希望以后台模式运行iOS应用程序,也不想从Apple Watch发出HTTP请求,则可以考虑另外两个选项。
1) 安排本地通知。 最好的部分是你的苹果手表应该运行didReceiveLocalNotification
,但不好的部分是,当你只是试图检查状态没有中断,用户会得到一个通知。
2)通过reloadTimelineForComplication
方法中的sendMessage(_:replyHandler:errorHandler:)
向iOS发送消息,为 reloadTimelineForComplication
设置nil
使其尽可能快:
当它处于活动状态并且正在运行时,从您的WatchKit扩展中调用此方法会在后台唤醒相应的iOS应用程序并使其可用。
您的iOS应用可以执行任何所需的networking请求,然后存储信息或将其推送到Apple Watch。 不幸的是,我不认为手表扩展会有它的session.didReceive...
调用,直到你运行它,但你可以访问下次调用requestedUpdateDidBegin
的数据。
正如我所说的,我对这件事情非常感兴趣,所以发表一些想法,也许我们可以推断一些最佳实践。