BGTaskScheduler 的后台获取与调试模拟完美配合,但在实践中从未奏效
Background fetch with BGTaskScheduler works perfectly with debug simulations but never works in practice
我在 appDelegate 的 didFinishLaunchingWithOptions 中注册了后台获取任务:
BGTaskScheduler.shared.register(forTaskWithIdentifier: BackgroundScheduler.shared.backgroundTaskId, using: DispatchQueue.main) { task in
BackgroundScheduler.shared.handleAppRefresh(task: task as! BGAppRefreshTask)
}
handleAppRefersh 函数安排另一个刷新任务并调用该操作的获取方法,并在完成获取操作后将完成处理程序传递给 运行。
func handleAppRefresh(task: BGAppRefreshTask) {
os_log("handleAppRefresh exetued.")
scheduleAppRefresh()
task.expirationHandler = {
os_log("backgroundFetch expiration called")
}
operation.fetch() {
os_log("backgroundFetch fetch called")
task.setTaskCompleted(success: true)
}
}
scheduleAppRefresh 提交 BGAppRefreshTAskRequest 以重复后台获取执行。
func scheduleAppRefresh() {
os_log("scheduleAppRefresh exetued.")
let request = BGAppRefreshTaskRequest(identifier: backgroundFetchId)
request.earliestBeginDate = Date(timeIntervalSinceNow: AppSettings.refreshInterval)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
os_log("Could not schedule app refresh:", error.localizedDescription)
}
}
刷新间隔为 10 * 60,即 10 分钟。
operation.fetch 方法检查设备的当前位置并向远程服务器发送请求。最后它发送本地通知,更新 UI 并调用以下代码:
task.setTaskCompleted(success: true)
在 Xcode 中检查了“位置更新”和“后台获取”功能,并在 info.plist 中添加了必需的设置。
当我使用以下调试命令测试后台获取功能时,一切正常,调试器中没有任何警告消息。
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"TASK_IDENTIFIER"]
但是当我将应用程序留在后台很长时间时,iOS 永远不会调用 handleAppRefresh 函数。
Xcode: 12.2, iOS: 14.2
项目 public 回购:
https://github.com/amirrezaeghtedari/CoronaVirousRegulations.git
我完全糊涂了。
据称,有很多因素在起作用,决定了您的应用何时实际运行后台刷新。 OS 的神经引擎了解用户何时启动应用程序,以便可以在之前执行更新。他们在 2019 年 session.
中首次提到了这一点
我将后台获取间隔设置为 10 分钟,在等待大约 4 小时或更长时间后,iOS 运行 我的应用程序在后台运行。之后,我的应用程序在后台不定期地被调用,间隔时间从不到一小时到几个小时不等。很明显,我的实现没有问题,这些执行间隔取决于 iOS 策略。
我在 appDelegate 的 didFinishLaunchingWithOptions 中注册了后台获取任务:
BGTaskScheduler.shared.register(forTaskWithIdentifier: BackgroundScheduler.shared.backgroundTaskId, using: DispatchQueue.main) { task in
BackgroundScheduler.shared.handleAppRefresh(task: task as! BGAppRefreshTask)
}
handleAppRefersh 函数安排另一个刷新任务并调用该操作的获取方法,并在完成获取操作后将完成处理程序传递给 运行。
func handleAppRefresh(task: BGAppRefreshTask) {
os_log("handleAppRefresh exetued.")
scheduleAppRefresh()
task.expirationHandler = {
os_log("backgroundFetch expiration called")
}
operation.fetch() {
os_log("backgroundFetch fetch called")
task.setTaskCompleted(success: true)
}
}
scheduleAppRefresh 提交 BGAppRefreshTAskRequest 以重复后台获取执行。
func scheduleAppRefresh() {
os_log("scheduleAppRefresh exetued.")
let request = BGAppRefreshTaskRequest(identifier: backgroundFetchId)
request.earliestBeginDate = Date(timeIntervalSinceNow: AppSettings.refreshInterval)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
os_log("Could not schedule app refresh:", error.localizedDescription)
}
}
刷新间隔为 10 * 60,即 10 分钟。
operation.fetch 方法检查设备的当前位置并向远程服务器发送请求。最后它发送本地通知,更新 UI 并调用以下代码:
task.setTaskCompleted(success: true)
在 Xcode 中检查了“位置更新”和“后台获取”功能,并在 info.plist 中添加了必需的设置。
当我使用以下调试命令测试后台获取功能时,一切正常,调试器中没有任何警告消息。
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"TASK_IDENTIFIER"]
但是当我将应用程序留在后台很长时间时,iOS 永远不会调用 handleAppRefresh 函数。
Xcode: 12.2, iOS: 14.2
项目 public 回购: https://github.com/amirrezaeghtedari/CoronaVirousRegulations.git
我完全糊涂了。
据称,有很多因素在起作用,决定了您的应用何时实际运行后台刷新。 OS 的神经引擎了解用户何时启动应用程序,以便可以在之前执行更新。他们在 2019 年 session.
中首次提到了这一点我将后台获取间隔设置为 10 分钟,在等待大约 4 小时或更长时间后,iOS 运行 我的应用程序在后台运行。之后,我的应用程序在后台不定期地被调用,间隔时间从不到一小时到几个小时不等。很明显,我的实现没有问题,这些执行间隔取决于 iOS 策略。