ios performFetchWithCompletionHandler 永远不会被解雇
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18315771/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
performFetchWithCompletionHandler never gets fired
提问by Clay Bridges
1) My plist configuration to provide backgroundmode:
1)我的plist配置提供backgroundmode:
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>
2) In didFinishLaunchingWithOptions
I have:
2)在didFinishLaunchingWithOptions
我有:
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:1.0];
3) I declared the protocol UIApplicationDelegate
in the delegate.
3)我UIApplicationDelegate
在委托中声明了协议。
4) I implemented the following method, but it never gets fired. (It only works if I simulate the fetch with "XCode->Debug->Simulate Background Fetch".)
4)我实现了以下方法,但它从未被解雇。(它仅在我使用“XCode->Debug->Simulate Background Fetch”模拟提取时才有效。)
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
Why? Is this a DP5 beta error? Should I radar this?
为什么?这是 DP5 测试版错误吗?我应该雷达吗?
采纳答案by One Man Crew
I'm afraid this is hard to debug on a device because you're not guaranteed it is called in the amount of time you specify.
恐怕这很难在设备上调试,因为您不能保证在您指定的时间内调用它。
setMinimumBackgroundFetchInterval
means that it is not called in an interval which is smaller than the value you specified. But there's no setMaximumBackgroundFetchInterval
.
So if iOS decides to call your app just once a day or even just once a week than it won't be called more often regardless your minimumBackgroundFetchInterval
. AFAIK iOS decides when to call performFetchWithCompletionHandler
measured by the pattern when and how often the users start's the app.
setMinimumBackgroundFetchInterval
意味着它不会在小于您指定的值的时间间隔内调用。但是没有setMaximumBackgroundFetchInterval
。因此,如果 iOS 决定每天只调用一次您的应用程序,甚至每周只调用一次,那么无论您的minimumBackgroundFetchInterval
. AFAIK iOS 决定何时调用performFetchWithCompletionHandler
由用户启动应用程序的时间和频率来衡量。
回答by Clay Bridges
In Xcode 5 Debug mode, you can force a background fetch from the menu: Debug > Simulate Background Fetch.
在 Xcode 5 调试模式下,您可以从菜单强制后台提取:调试 > 模拟后台提取。
回答by Rob
There are many considerations:
有很多考虑:
Make sure the background fetch capability was set in the plist.
Make sure the background fetch capability hasn't been disabled for this particular app, or in general, in the device's Settings app.
Make sure to set the minimum fetch interval.
Make sure you gracefully leave the app (e.g. just hit the home button and fire up another app and/or just lock the device). But if you kill the app (double tapping on the home button and swiping up, or what have you) that will prevent the OS from offering your app a chance to fire off subsequent background fetch requests (at least until the user runs the app again).
Make sure you are testing this on physical device and not running the app via the Xcode debugger. Being attached to the debugger changes the behavior of background operations.
Make sure the app is actually doing some network requests. If you have app that performs no network requests at all, it won't participate in background fetch. If you do, for example, a little test app with "background fetch" and don't issue any network requests, you won't participate in background fetch.
Likewise, if the OS starts up your app in background mode so it can perform a background fetch, if you don't actually perform a network request, the OS may stop offering your app the ability to perform background fetches in the future.
Make sure to call the completion handler, and do so within the allotted time, or your app may not participate in background fetch in the future.
The timing of when the OS performs background fetch is dictated by poorly documented rules that may change in the future. But the relevant factors include:
Whether the device is connected to power and/or is sufficiently charged;
Whether connected to WiFi or not;
How often the user actually fires up the app;
Whether the device is doing other network related tasks (e.g. whether background fetch can be coalesced with other network operations);
How frequently past background fetch requests resulted in there being data available.
In my experience, after the app is run the first time, if connected to wifi and power, if you wake the device about 5 minutes later, the app will perform background fetch. This isn't a hard and fast rule, but just what we've experienced in the past.But many new developers post on Stack Overflow with questions like "how can I have app request data ever xminutes (or hours)", "how can I request data every day at 2 am time", etc. The short answer is that you can't. The OS decides the timing of background at its own discretion. You cannot control this (other than the minimum request interval; but you cannot control the maximum interval, as the OS controls that).
This may seem obvious to many, but make sure you've got a reliable way of knowing whether background fetch process is running correctly or not. User Notifications framework can be used to present some alert so you know if the background request resulted in something. Alternatively,
os_log
"Unified Notifications" can be used to post messages on device that can be monitored on macOSConsole
app. But more than once, I've seen users do something like waiting for message to show up in Xcode or waiting forUIAlertController
. You need some mechanism that works when not connected to Xcode and when the app never enters foreground.
确保在 plist 中设置了后台获取功能。
确保没有为此特定应用程序禁用后台提取功能,或者通常在设备的设置应用程序中禁用。
确保设置最小获取间隔。
确保您优雅地离开应用程序(例如,只需点击主页按钮并启动另一个应用程序和/或只是锁定设备)。但是,如果您终止应用程序(双击主页按钮并向上滑动,或者您有什么),这将阻止操作系统为您的应用程序提供触发后续后台获取请求的机会(至少在用户再次运行该应用程序之前) )。
确保你是在物理设备上测试这个,而不是通过 Xcode 调试器运行应用程序。附加到调试器会改变后台操作的行为。
确保应用程序实际上正在执行一些网络请求。如果您的应用根本不执行网络请求,则它不会参与后台提取。例如,如果你做一个带有“后台获取”的小测试应用程序并且不发出任何网络请求,你将不会参与后台获取。
同样,如果操作系统在后台模式下启动您的应用程序以便它可以执行后台提取,如果您实际上没有执行网络请求,操作系统可能会停止为您的应用程序提供执行后台提取的功能。
确保调用完成处理程序,并在分配的时间内完成,否则您的应用将来可能不会参与后台提取。
操作系统执行后台提取的时间由记录不良的规则决定,这些规则将来可能会发生变化。但相关因素包括:
设备是否已接通电源和/或是否充满电;
是否连接WiFi;
用户实际启动应用程序的频率;
设备是否正在执行其他网络相关任务(例如后台获取是否可以与其他网络操作合并);
过去后台获取请求导致数据可用的频率。
以我的经验,应用程序第一次运行后,如果连接到wifi和电源,如果您在大约5分钟后唤醒设备,应用程序将执行后台提取。这不是硬性规定,而是我们过去所经历的。但是许多新开发人员在 Stack Overflow 上发帖提出了诸如“我怎样才能在x分钟(或几小时)内获得应用程序请求数据”、“我怎样才能在每天凌晨 2 点时间请求数据”等问题。简短的回答是您不能。操作系统自行决定后台的时间。您无法控制这一点(最小请求间隔除外;但您无法控制最大间隔,因为操作系统会对此进行控制)。
这对许多人来说似乎很明显,但请确保您有一种可靠的方法来了解后台提取过程是否正确运行。用户通知框架可用于呈现一些警报,以便您知道后台请求是否导致了某些事情。或者,
os_log
“统一通知”可用于在可在 macOSConsole
应用程序上监控的设备上发布消息。但不止一次,我看到用户做一些事情,比如等待消息显示在 Xcode 中或等待UIAlertController
. 您需要一些在未连接到 Xcode 和应用程序从未进入前台时工作的机制。
回答by user1700099
(It only works if I simulate the fetch with "XCode->Debug->Simulate Background Fetch".)
(它仅在我使用“XCode->Debug->Simulate Background Fetch”模拟提取时才有效。)
It's because you're in Debug mode. Please try launch app without XCode.
这是因为您处于调试模式。请尝试在没有 XCode 的情况下启动应用程序。
回答by user2936585
Using your device you can fire application:performFetchWithCompletionHandler
with the following steps:
使用您的设备,您可以application:performFetchWithCompletionHandler
通过以下步骤启动:
- Put your app in the Background state
- Lock your device and wait 5 minutes.
- Unlock your device, this will fire the method
- 将您的应用程序置于后台状态
- 锁定您的设备并等待 5 分钟。
- 解锁您的设备,这将触发该方法
回答by Axeva
Another thing to check is your plist
file. Make sure the UIApplicationExitsOnSuspend
key is not present.
要检查的另一件事是您的plist
文件。确保UIApplicationExitsOnSuspend
密钥不存在。
Many people here on Stack Overflow have recommended using that setting as a way to force your app to start fresh each time it's launched. That does work, but the side effect is that it prevents the new iOS 7 background fetch feature from being triggered.
Stack Overflow 上的许多人建议使用该设置作为强制应用程序每次启动时重新启动的一种方式。这确实有效,但副作用是它阻止了新的 iOS 7 后台获取功能被触发。
回答by Anastasia
If application: performFetchWithCompletionHandler:
never gets fired (unless you simulate it using Xcode), check also if "Background App Refresh" preference is "On" for your app. (Settings app -> General -> Background App Refresh)
如果application: performFetchWithCompletionHandler:
从未被触发(除非您使用 Xcode 模拟它),还要检查您的应用程序的“后台应用程序刷新”首选项是否为“开”。(设置应用 -> 通用 -> 后台应用刷新)
回答by adrian1kat
Also, background fetch is disabled if the iPhone is in Low Power Mode.
此外,如果 iPhone 处于低功耗模式,后台获取将被禁用。
回答by CrazyDeveloper
Apple provides an algorithm which defines how often the background fetch should trigger, based on your own usage of the app. If you use it a lot, then it will fetch as often as possible, but if you use like at 4pm every day, the background fetch should trigger just before, so your data is updated when you launch it. Refer this link
Apple 提供了一种算法,该算法根据您自己对应用程序的使用情况来定义应触发后台获取的频率。如果你经常使用它,那么它会尽可能频繁地获取,但如果你每天下午 4 点使用它,后台获取应该在之前触发,所以当你启动它时你的数据会更新。参考这个链接