何时何地获取手表复杂功能的数据?

33

经过数天的复杂操作后,我对按预定时间间隔更新的更新流程有信心地说出以下内容:

  • 系统调用requestedUpdateDidBegin()
    • 在这里,您可以确定您的数据是否更改。如果没有更改,您的应用程序无需做任何事情。如果您的数据已更改,则需要调用以下方法之一:
      • 如果需要重置所有数据,请使用reloadTimelineForComplication
      • 如果只需要将新项添加到并发症时间线的末尾,请使用extendTimelineForComplication
    • 注意:如果你的复杂性时间预算超支了,系统实际上可能会调用requestedUpdateBudgetExhausted()而不是requestedUpdateDidBegin()。这就是这个问题的原因。
  • 如果您调用了reloadTimelineForComplication,系统将调用getCurrentTimelineEntryForComplication(连同获取数组的未来和过去变体,具体取决于您的时空旅行设置)
  • 这是推测,因为我还没有测试过,但我认为如果您调用了extendTimelineForComplication,那么仅会调用getTimelineEntriesForComplication(... afterDate date: NSDate ...)
  • 然后,系统将调用getNextRequestedUpdateDateWithHandler,以便您指定多长时间才需要新的更新。

苹果的文档非常清楚,您不应过于频繁地要求更新,或在并发症代码中进行太多处理,否则您的时间预算将耗尽,并且并发症将停止更新。那么,我的问题是:您何时何地进行更新?

为了背景,我的情况是一个URL,返回数据每小时更改最多两次。

最明显的放置URL获取代码的位置是func requestedUpdateDidBegin()。获取数据,存储它,如果没有更改,则只需返回。如果有更改,则扩展或重新加载时间线。

然而,URL抓取可能会很昂贵。替代方案:

  • 将代码放在手机应用程序中,并使用WCSession发送,但如果用户关闭该应用程序,则更新将不再发生。
  • 使用推送更新,但这不是Web应用程序,因此我无法从其中发送它们。
  • 显然,当用户与手表应用程序交互时,我将更新所有数据,但这意味着仅在用户使用应用程序时才会更新数据,这就否定了需要使用复杂功能的原因。

还有其他地方吗?我能否在手表应用程序中拥有一个周期性函数,而不是作为复杂功能的一部分?哪里是为复杂功能更新获取数据的正确位置?


我还注意到requestedUpdateDidBegin()可能不会计入您的时间预算。显然,重新加载和扩展的调用都会计入预算。因此,在缺乏其他信息的情况下,我倾向于在requestedUpdateDidBegin()中执行操作,但我仍在寻找实际答案,而不是我的猜测... - El Tea
1
你介意分享一些关于如何实现requestedUpdateDidBegin、reloadTimeLineForComplication和getCurrentTimelineEntryForComplication的代码吗?我一直在尝试实现它们以执行网络请求并每两个小时更新复杂性,但在初始设置后绝对没有任何反应。它总是显示原始数据。 - swiftyboi
B K - 我很乐意。为什么不提出一个新问题并链接它呢?我会在明天放上我的代码。 - El Tea
1
我昨晚实际上就问过这个问题了!这是链接:https://dev59.com/6uk6XIcBkEYKwwoYEf0H - swiftyboi
2个回答

29

对于watchOS 3,苹果建议您从使用复杂数据源getNextRequestedUpdateDate计划更新转换为更新您的复杂性。

watchOS 2的旧方法

requestedUpdateDidBegin()实际上只是用于更新复杂性。保持您的复杂性(和手表应用程序)通常涉及远不止重新加载时间线(异步检索数据从未很好地适合旧方法)。

watchOS 3的新方法

新的更好的方法是使用后台刷新应用程序任务。您可以使用一系列后台任务来安排处理在后台唤醒您的应用程序扩展:

在任务完成后立即调用每个任务的setTaskCompleted方法。

使用应用程序任务的其他好处

这种设计的关键特点之一是,手表扩展现在可以处理各种前景和背景场景,包括:

  • 当您的应用程序/组件启动时,最初加载数据,
  • 在后台更新数据,当扩展被后台任务唤醒时,
  • 在前台更新数据,当用户从Dock中恢复您的应用程序时。

苹果建议您利用每个机会来保持您的组件、应用程序和Dock快照的最新状态,无论您的应用程序是在前台还是后台

有任何限制吗?

每天可用的总任务数将分配给Dock中的应用程序数量。Dock中的应用程序越少,您的应用程序可以利用的任务就越多。Dock中的应用程序越多,您可以利用的任务就越少。

  • 如果您的组件处于活动状态,则您的应用程序至少可以每小时唤醒四次。

  • 如果您的组件未处于活动状态,则保证每小时至少唤醒一次您的应用程序。

由于您的应用程序现在正在后台运行,因此您需要高效快速地完成后台任务。

后台任务受到CPU时间和CPU使用量的限制。如果超过CPU时间(或在后台使用超过10%的CPU),系统将终止您的应用程序(导致崩溃)。

了解更多信息


1
有没有一种首选的方式在后台更新位置,比如说如果你需要在进行URLSession之前获取当前位置? - corradio
1
警告!在watchOS 4中,使用新方法是强制性的。如果在iOS11 / watchOS4下编译,使用旧方法构建的应用程序将无法更新其并发症,并且getNextRequestedUpdateDate在调用时除了在控制台中给出警告消息外什么也不做。 - gpdawson

3

编辑:El Tea (op)在https://dev59.com/6uk6XIcBkEYKwwoYEf0H#32994055上发布了一个很好的答案

这是一个有趣的问题/问题,我一直在想同样的事情!

大多数情况下,似乎当我正在处理新的复杂情况时,需要退后一步,看看我真正想要更新它的时间。倒计时的复杂情况可以在“结束日期”设置时一次设置所有未来时间轴条目。显示Web服务当前状态的应用程序可以在APNS到达时将相关数据存储在NSUserDefaults中。

如果您没有访问APNS,不想在后台模式下运行iOS应用程序,并且不想从Apple Watch发出HTTP请求,则我可以想到另外2个选项。

1)调度本地通知。 好处是您的Apple Watch应该运行didReceiveLocalNotification,但坏处是用户会在您只是尝试检查状态而没有干扰时收到通知。

2)通过sendMessage(_:replyHandler:errorHandler:)在您的reloadTimelineForComplication方法中发送消息到iOS,将nil设置为replyHandler 以尽可能快地完成:

在WatchKit扩展处于活动和运行状态时从中调用此方法会唤醒相应的iOS应用程序并使其可达。

您的iOS应用程序可以执行所需的任何网络请求,然后存储信息或将其推送到Apple Watch。不幸的是,我认为手表扩展名将不会调用其session.didReceive ...,直到您运行它,但您可以在下一次调用requestedUpdateDidBegin时访问数据。

正如我所说,我对这个问题非常感兴趣,因此发表一些想法,也许我们可以在这里推导出一些最佳实践。


1
当你关闭iOS应用程序时,它可以请求额外的时间,但据我所知,这最多只能进行10分钟以执行所需的任何任务。唯一的其他选项是在“后台模式”下继续运行,即VoIP呼叫、地图方向等,其中应用程序仍在顶部显示绿色条。那绝对不是我们要寻找的。 - Charlie Schliesser
1
访问https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html并向下滚动到表3.1。也许您实际上应该在“获取”背景模式下运行。我想制作一个小的示例应用程序,正是这样做,并将数据传回到一个复杂的地方。 - Charlie Schliesser
1
@Philippe:抱歉,这只是我的业余爱好。我有一些东西,明天会更新。这很复杂,因为它真的取决于你的使用情况,但我会尝试通过几种场景来解释。 - El Tea
1
这里的问题是:我们正在寻找最佳实践方案,但不知道苹果正在跟踪执行使用情况的位置。在文档中,requestedUpdateDidBegin()没有特别提及执行预算。然而,reloadTimelineForComplication()指出:“请谨慎调用此方法”,并且“如果您的并发症已经超过了其分配的每日执行时间预算,对此方法的调用将不起任何作用。” 我现在的计划是编写一个程序,以显示requestedUpdateDidBegin()是否正在消耗执行预算。如果我无法证明这一点,那么我仍然有一些最佳实践可以提出。 - El Tea
2
上次测试的最终结果:在大约10小时内,每10分钟进行60次计算。使用了52秒的CPU时间。从未遇到过不合理的延迟,并且没有出现0个“requestedUpdateBudgetExhausted()”调用。所以我真的不知道苹果是如何限制这个的。我知道的是它耗尽了我的电池。我的正常使用方式可以让我在睡前达到50%,但我的手表已经没电了。因此,显然您不希望在手表上进行大量计算。如果时间允许,我将在明天查看所学到的教训和最佳实践。 - El Tea
显示剩余14条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接