【问题标题】:How to tell if iOS Today Widget is being updated in the background?如何判断 iOS Today Widget 是否在后台更新?
【发布时间】:2026-01-15 02:00:01
【问题描述】:

我有一个 iOS Today 小部件,它进行昂贵的 API 调用(昂贵,因为调用的次数越多,我付的钱就越多)。如果我在我的小部件中实现了 widgetPerformUpdateWithCompletionHandler,那么小部件可以在一天中在后台更新几次,而用户无需查看他们的通知中心。

在应用程序中,应用程序的选项字典中有一个键值对:didFinishLaunchingWithOptions 告诉您应用程序是否正在启动后台,但在小部件中我找不到任何类似的东西.在 UIApplication 中还有获取 applicationState 的调用,这在小部件中也是不可用的。

那么,在我的小部件中是否有任何可靠方法可以知道系统正在后台更新我的小部件并且用户没有查看他们的通知中心来避免不必要的 API 调用?当用户确实查看小部件时,我对内容没有完全更新感到满意,因为我可以在它加载后很快更新它。

我一直在尝试找到一个 hacky 解决方案,例如在后台更新小部件时视图或窗口不同,但还没有找到任何东西。我注意到偶尔在后台初始化小部件时,窗口框架的高度为零,但似乎并非总是如此。

我也知道,如果我不实现 widgetPerformUpdateWithCompletionHandler,那么我的小部件不会在后台更新,这是一个可能的解决方案,但我正在寻找一种可以吃蛋糕的方法也是。

如果有人有任何其他想法,我会全力以赴。谢谢。

【问题讨论】:

    标签: ios ios9 today-extension


    【解决方案1】:

    如果您只是计划调试并了解它被调用的频率,您可以在设备上使用一些日志记录(甚至可能在每次调用 widgetPerformUpdateWithCompletionHandler 时触发某种分析事件通知,以调解是否发生得太频繁了)。

    减少请求数量的主动解决方案的一个示例是对请求进行计时,如果 widgetPerformUpdateWithCompletionHandlerx 分钟/小时/等运行一次以上,您将不会调用 API但只需在没有新数据的情况下调用completionBlock

    对 API 调用进行更严格限制的最后一个示例可能是在 Today's 扩展中完全避免它们(就像你说的那样)。这意味着 API 调用只会在实际应用程序启动时完成,并且响应持续存在(您可以在应用程序和 Today 的扩展程序之间拥有一个共享容器 - 只是一个文件夹,甚至更复杂的东西,比如 Core Data 的 sqlite 存储) 并始终从共享容器中检索数据以更新 Today's 扩展 UI。

    【讨论】:

    • 感谢您的建议。不幸的是,我想确保在用户打开通知中心并看到小部件时立即调用 API。因此,时间门控和仅在应用程序中更新是不够的解决方法。
    • 仅当正在显示的小部件的viewDidLoad 被调用时才进行调用呢?作为一个昂贵的呼叫并且也可能在一个缓慢的网络中可能意味着请求和响应之间会有轻微的延迟,但这将确保如果扩展是从用户的操作而不是后台触发器中提取的,那么请求就会被发出.
    • viewDidLoad、viewWillAppear 等即使在后台更新时也会被调用,大概是因为它正在对最终视图进行快照。并且在这两种情况下都会调用 widgetPerformUpdateWithCompletionHandler。因此我无法判断小部件是否在后台运行。
    • 当您的小部件不在屏幕上时,不会调用视图生命周期调用。不知道“即使它在后台更新”是什么意思
    • 当您的小部件不在屏幕上时,它们确实会被调用。我为每次通话都输入了日志消息,果然,即使手机被锁定,这些消息也会显示出来,当后台从系统中触发 widgetPerformUpdateWithCompletionHandler 时,屏幕会关闭。
    【解决方案2】:

    我为此提交了 Apple Developer Technical Support 票证。他们回应并告诉我,我不可能为此提出增强请求。我提交了 rdar://27434852。

    【讨论】:

      【解决方案3】:

      widgetPerformUpdateWithCompletionHandler 在 iOS 9 中实际上是相当不可靠的。如果你只是在后台从viewDidLoad 启动你的网络调用,它只会在你的今日小部件出现在屏幕上时被调用。

      【讨论】:

      • 它不可靠,因为你永远不知道它什么时候会在后台启动,但它似乎在我的测试中经常运行,有时每小时不止一次。而当它在后台运行时,viewDidLoad、viewWillAppear、viewDidAppear 都会运行。因此,不幸的是,当小部件在后台时,在 viewDidLoad 中执行的操作将会运行。
      • 它不可靠,因为即使在前台也不总是被调用。我测试这个已经有一段时间了,但我认为如果你不实现widgetPerformUpdateWithCompletionHandler,你不会在后台收到任何生命周期调用
      • 对,我同意如果你不实现widgetPerformUpdateWithCompletionHandler,小部件永远不会在后台被唤醒。这是 Apple 正确记录此电话的少数几件事之一。不实现此调用的缺点是,当通知中心未暂停在内存中并且需要从头开始初始化时,打开通知中心时,小部件可能需要更长的时间才能出现。实现 widgetPerformUpdateWithCompletionHandler 通常会导致小部件经常挂在内存中,从而使其更快出现。所以我希望保留它。
      • 啊,我从您的评论I'm fine with the content not being completely up to date when the user does look at the widget because I can update it pretty quickly after it loads 中得知这没什么大不了的。我不知道实现widgetPerformUpdateWithCompletionHandler 对系统将您的小部件保留在内存中有任何影响。
      最近更新 更多