【问题标题】:performFetchWithCompletionHandler never gets firedperformFetchWithCompletionHandler 永远不会被解雇
【发布时间】:2013-08-21 08:47:20
【问题描述】:

1)我的plist配置提供backgroundmode:

<key>UIBackgroundModes</key>
<array>
    <string>fetch</string>
</array> 

2) 在didFinishLaunchingWithOptions 我有:

[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:1.0];

3) 我在委托中声明了协议UIApplicationDelegate

4) 我实现了以下方法,但它从未被触发。 (仅当我使用“XCode->Debug->Simulate Background Fetch”模拟提取时才有效。)

-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

为什么?这是 DP5 测试版错误吗?我应该雷达吗?

【问题讨论】:

  • 您是在模拟器和/或真实设备上试用您的应用程序吗?
  • 我与 iOS 7 的发布版本完全一样。当我在 Xcode 中手动触发后台提取时,它工作得很好,但似乎从未在实际设备上触发。我们如何诊断问题的原因?

标签: ios objective-c ios7


【解决方案1】:

恐怕这很难在设备上调试,因为你不能保证它会在你指定的时间内被调用。

setMinimumBackgroundFetchInterval 表示它不会在小于您指定的值的间隔内调用。但是没有setMaximumBackgroundFetchInterval。 因此,如果 iOS 决定每天或什至每周只调用一次您的应用程序,那么无论您的minimumBackgroundFetchInterval,它都不会被更频繁地调用。 AFAIK iOS 决定何时调用performFetchWithCompletionHandler,由用户启动应用程序的时间和频率来衡量。

【讨论】:

  • 谁能详细说明这个答案? “你不知道什么时候,你永远也不知道什么时候”可能是正确的答案,但我真的希望我们能做得更好。如果我们无法区分“出了什么问题”和“你的时间还没到”,那么调试后台获取进程几乎是不可能的。
  • 当设备处于锁定状态且未连接到 Wi-Fi 时,我看到刷新时间在 10 到 20 分钟之间。唤醒设备可以提前触发刷新,但不能在 5 分钟内触发。
  • 即“最小”是指如果 iOS 决定调用应用程序调用之间的缩短时间间隔。在“最短”时间过后,何时调用由 iOS 决定,无需立即调用。这是什么意思?谢谢!
  • 如果有人可以添加一些关于 iOS 用来决定何时调用它的指标以及可能使其调用频率降低的事情的解释,那就太好了?
【解决方案2】:

在 iOS 模拟器中运行您的应用,在 Xcode 调试模式下,您可以从 Xcode 菜单强制执行后台获取:

调试 > 模拟后台获取

可能适用于系留设备,我最近没有尝试过。

【讨论】:

  • 这行得通。每次选择上述项目时,都会调用一次回调方法。 (据我所知,没有重复)。
  • 执行此操作时还可以看到明显的崩溃stackoverflow.com/questions/39623664/…
  • 你拯救了我的夜晚!
  • 这在连接到调试器时有效,并且调试器阻止 iOS 触发获取。要让 iOS 触发,您必须从 Xcode 9.4 开始与调试器分离。
【解决方案3】:

使用您的设备,您可以通过以下步骤触发application:performFetchWithCompletionHandler

  • 将您的应用置于后台状态
  • 锁定您的设备并等待 5 分钟。
  • 解锁您的设备,这将触发该方法

【讨论】:

  • 有趣的是,这很有效。如果设备关闭,为什么它永远不会被调用?我在那里坐了整整一个小时,什么也没发生。我一解锁手机,它就起作用了。这个抓取功能太没有意义了
  • 成功了。感谢您提供此信息。问题:是解锁会触发该方法吗?还是会在锁定时触发?
  • 如果我将锁定选项设置为从不设置会怎样?
【解决方案4】:

要检查的另一件事是您的plist 文件。确保UIApplicationExitsOnSuspend 键不存在。

Stack Overflow 上的许多人都建议使用该设置来强制您的应用在每次启动时重新启动。这确实有效,但副作用是它阻止了新的 iOS 7 后台获取功能被触发。

【讨论】:

    【解决方案5】:

    如果application: performFetchWithCompletionHandler: 从未被触发(除非您使用 Xcode 模拟它),请检查您的应用程序的“后台应用程序刷新”首选项是否为“开启”。 (设置应用 -> 常规 -> 后台应用刷新)

    【讨论】:

    • iOS7:选择目标,Capabilities>BackgroundModes
    【解决方案6】:

    (仅当我使用“Xcode->Debug->Simulate”模拟提取时才有效 后台获取”。)

    这是因为您处于调试模式。请尝试在没有 Xcode 的情况下启动应用程序。

    【讨论】:

    • 因为在这种模式下,iOs 无法收集您应用的真实使用情况统计信息。该值是计算获取间隔的必需值。
    • 这确实有效!用于计算获取间隔的“使用统计”是否有任何官方参考?
    • 我能够使用@user2936585 方法触发获取,因此“仅在...时才有效”不准确。 XCode->Debug->Simulate Background Fetch 确实有效,但将应用程序置于后台,锁定设备,等待五分钟也是如此。后者确实适用于调试构建,但在连接到调试器时不适用。
    【解决方案7】:

    Apple 提供了一种算法,该算法根据您自己对应用程序的使用情况定义后台提取应该触发的频率。如果你经常使用它,那么它会尽可能频繁地获取,但如果你在每天下午 4 点使用 like,后台获取应该在之前触发,所以当你启动它时你的数据会更新。

    【讨论】:

    【解决方案8】:

    此外,如果 iPhone 处于低功耗模式,后台获取将被禁用。

    【讨论】:

      【解决方案9】:

      有很多考虑:

      1. 确保在 plist 中设置了后台获取功能。

      2. 确保没有为此特定应用禁用后台获取功能,或者通常在设备的“设置”应用中禁用。

      3. 确保设置最小获取间隔。

      4. 确保您优雅地离开应用程序(例如,只需点击主页按钮并启动另一个应用程序和/或只是锁定设备)。但是如果你杀死了应用程序(通过双击主页按钮并向上滑动来“强制退出”,或者对于那些没有主页按钮的设备,从底部向上滑动以拉出任务管理器,然后在应用程序上向上滑动问题),这将阻止操作系统为您的应用提供触发后续后台获取请求的机会(至少在用户再次运行应用之前)。

      5. 确保您是在物理设备上进行测试,而不是通过 Xcode 调试器运行应用程序。附加到调试器会改变后台操作的行为。

      6. 确保应用确实在执行一些网络请求。如果您的应用根本不执行任何网络请求,它就不会参与后台获取。例如,如果您使用“后台获取”的小测试应用程序并且不发出任何网络请求,则您将不会参与后台获取。

        同样,如果操作系统在后台模式下启动您的应用以便执行后台提取,如果您实际上没有执行网络请求,操作系统可能会在未来停止为您的应用提供执行后台提取的能力.

      7. 确保调用完成处理程序,并在分配的时间内这样做,否则您的应用将来可能不会参与后台提取。

      8. 操作系统执行后台提取的时间取决于记录不充分的规则,这些规则将来可能会发生变化。但相关因素包括:

        • 设备是否已连接到电源和/或是否充满电;

        • 是否连接到WiFi;

        • 用户实际启动应用的频率;

        • 设备是否正在执行其他网络相关任务(例如,后台获取是否可以与其他网络操作合并);

        • 过去的后台获取请求导致有可用数据的频率。

        根据我的经验,应用程序第一次运行后,如果连接到 wifi 和电源,如果您在大约 5 分钟后唤醒设备,应用程序将执行后台获取。这不是硬性规定,而是我们过去所经历的。

        但许多新开发人员在 Stack Overflow 上发帖提问,例如“我怎样才能在 x 分钟(或几小时)内获得应用请求数据”、“我怎样才能在每天凌晨 2 点请求数据”等。简短的回答是你不能。操作系统自行决定后台的时间安排。您无法控制这一点(除了最小请求间隔;但您无法控制最大间隔,因为操作系统可以控制)。

      9. 这对许多人来说似乎很明显,但请确保您有可靠的方法来了解后台提取进程是否正确运行。用户通知框架可用于显示一些警报,以便您知道后台请求是否导致某些事情。或者,os_logLogger“统一日志记录”(参见 WWDC 2016 Unified Logging and Activity Tracing 或 2020 的 Explore logging in Swift)可用于在可在 macOS Console 应用程序上监控的设备上发布消息。但不止一次,我看到用户做一些事情,比如等待消息出现在 Xcode 中或等待UIAlertController。您需要一些在未连接到 Xcode 且应用从不进入前台时起作用的机制。

      【讨论】:

      • 好答案。但是,这里应用程序在调试设备上 24 小时后第一次启动 performFetchWithCompletionHandler。更改了很多参数,但在 1 小时内无法使其工作(setMinimumBackgroundFetchInterval 设置为 10 分钟,3 小时,最小值不会改变任何东西。
      • “确保应用程序确实在执行一些网络请求。”来源?
      • @IulianOnofrei - 后台获取更多实际执行网络请求:这是在 WWDC 会议上讨论的。显然,如今,您通常使用BGAppRefreshTask 来处理带有网络请求的刷新任务,而BGProcessingTask 来处理任务。
      • @IulianOnofrei - 重新杀死应用程序:无意冒犯,我不相信你是正确的。从 iOS 7 开始,强制退出应用程序也会阻止大多数后台操作。旧的“iOS 应用程序编程指南”说(除了一些与位置相关的功能),“系统不会在用户强制退出后重新启动应用程序[在后台]......用户必须启动显式应用程序或重新启动设备,然后系统才能将应用程序自动启动到后台”。强制退出是停止与应用相关的任务。
      • 哇,显然,there is a difference 在用户强制退出应用程序和应用程序被系统关闭或崩溃之间。我一直认为它们的处理方式相同:应用程序完全关闭。
      猜你喜欢
      • 2016-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-11
      • 2018-01-07
      • 1970-01-01
      相关资源
      最近更新 更多