代码之家  ›  专栏  ›  技术社区  ›  Lebecca

为什么iOS小部件即使在前台有包含应用程序的情况下也不能及时刷新

  •  0
  • Lebecca  · 技术社区  · 2 年前

    我对iOS小部件刷新机制做了一些研究:

    1前台包含应用程序时,小部件刷新不受限制

    阅读 apple developer docs ,我了解到小部件刷新由WidgetKit预算控制。正如它所说:

    对于用户经常查看的小部件,每天的预算通常包括40到70次刷新

    但在以下情况下,重新加载不计入小部件预算:

    • 包含应用程序的小部件在前台。
    • 包含应用程序的小部件具有活动的音频或导航会话。
    • 系统区域设置更改。
    • 动态类型或辅助功能设置更改。

    2我们可以使用 WidgetCenter.shared.reloadTimelines 从包含应用程序中刷新小部件

    同一位医生说:

    在上面的游戏小部件示例中,如果应用程序收到一个推送通知,指示队友给了角色治疗药剂,则应用程序可以告诉WidgetKit重新加载时间线并更新小部件内容。

    3我看到了一些很好的实现

    类似的应用程序 LiveIn 当我收到朋友的帖子时,小部件会及时刷新,给我一个流畅的用户体验(只要包含的应用程序在前台,我想他们可以通过 Background Refresh )。

    该产品不受每天40到70次刷新预算限制,并且我在包含应用程序和小部件的图片显示之间有一点延迟(小到可以忽略)。

    4但我还是被困在这里

    但是当我尝试使用上面的API构建一个应用程序时 小工具中心共享加载时间线 WidgetCenter.shared.reloadAllTimelines 通知小部件使用存储在中的数据进行刷新 UserDefaults ,我的小部件没有及时响应API调用。有时,它可能会卡住10分钟以上,这是一个与我上面提到的产品相去甚远的可怕情况。

    5一些黑客攻击尝试

    我看了这么多Stackoverflow的QA&博客,并且确实在iOS小部件中发现了一些棘手的事情。例如 View._clockHandRotationEffect(.secondHand, in: .current, anchor: .center) API可用于无限制地刷新小部件视图(通常用于构建基于时钟的应用程序)。

    但这似乎与包含应用程序和小部件之间的消息通知无关(或者只是我还没有弄清楚)。

    6我的问题

    所以我的问题来了。既然iOS商店中的一些应用程序已经能够及时通知小工具,为什么我仍然不能在官方文档的指导下获得流畅的用户体验?我是错过了一些重要的东西,还是他们只是在使用我看不见的其他私有API?

    代码并不复杂,Xcode签名也很烦人,所以我没有准备一个最小的项目来复制它。你可以 pawello2222/WidgetExamples 作为一个演示,如果你想试一试的话。任何提示或线索都将不胜感激!

    0 回复  |  直到 2 年前
        1
  •  2
  •   Lebecca    2 年前

    最后,我们获得了流畅的用户体验。乍一看,这个解决方案很奇怪,但与我们早期的实现相比,它的工作方式很有魅力。

    你所需要做的就是打电话 WidgetCenter.shared.reloadTimelines WidgetCenter.shared.reloadAllTimelines 在应用程序尽快进入前台之后。

    为什么?作为医生 Managing Your App's Life Cycle 状态:

    前台应用程序吸引了用户的注意力,因此它优先于系统资源,包括CPU

    文档很清楚,但时间也很重要,我们测试了一些现象,但在任何官方文档中都找不到(在发布时运行应用程序,而不是连接xcode的调试模式):

    • 始终在前台启动应用程序,通过调用通知小部件刷新视图 小工具中心共享加载时间线 小工具中心共享加载所有时间线 随着时间的推移,延迟会不断增加
    • 打电话时 小工具中心共享加载时间线 小工具中心共享加载所有时间线 应用程序尽快启动后,小部件视图将立即刷新(几乎100%的成功率)

    我看到许多开发人员陷入了iOS小部件的刷新之谜,最终放弃了使用它。希望我的经历能帮助其他人更好地理解并更快地做出决定。

        2
  •  1
  •   Boon    2 年前

    @Lebecca我只是想从我这边补充更多的见解。希望你觉得它有帮助。

    在我的应用程序中,我在应用程序进入后台之前调用WidgetCenter.shared.loadAllTimelines。我对这个重新加载没有任何问题。重新加载成功率为100%。

    根据我的经验,当应用程序进入后台时,你有几秒钟的时间来做一些工作,然后这个过程就会终止。您的小部件可能需要比允许的时间更多的时间来重新加载。这就是为什么您看不到“重新加载”的一致性。您在应用程序进入前台后立即调用WidgetCenter.shared.loadTimelines的解决方案解决了这一问题,因为您给了小部件“更多”的时间来完成重新加载。(当应用程序处于前台时,您对处理时间没有限制。)

    有3个部分涉及小部件重新加载。

    1. 小工具的数据:如果你的应用程序需要运行一些代码或从网络中检索一些信息。请确保它不会花费太长时间,否则小部件重新加载过程可能会被终止。

    2. 小部件的复杂性:这里我指的是您的小部件视图是否复杂。许多堆栈、许多元素可能会导致小部件重新加载失败。

    3. 你有多少时间线条目:假设你一天有100个时间线条目,这也可能会导致一些问题。你需要找到时间线条目和你计划在一天内运行的重新加载次数的平衡。

    4. 小工具重新加载预算。为了安全起见,我总是尽量每天保持40-50次左右。

    小工具真的是个谜。以上都是我的经验。