尝试使用 BGAppRefreshTask 并收到错误 没有计划具有标识符<解码:缺少数据>的任务请求



我一直得到错误

No task request with identifier <decode: missing data> has been scheduled

在我的调试器输出中,所以我决定尝试运行苹果提供的示例代码,并得到相同的错误。我已经尝试了多个计算机和Xcode版本,来自不同来源的多个示例项目,没有任何工作。

我的AppDelegate.swift文件:

import UIKit
import Firebase
import BackgroundTasks
@main
class AppDelegate: UIResponder, UIApplicationDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

FirebaseApp.configure()

BGTaskScheduler.shared.register(forTaskWithIdentifier: “redacted.identifier”, using: nil) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}

return true
}

func applicationDidEnterBackground(_ application: UIApplication) {
BGTaskScheduler.shared.cancelAllTaskRequests()
scheduleAppRefresh()
}

func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "redacted.identifier")

request.earliestBeginDate = Date(timeIntervalSinceNow: 60)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh: (error)")
}
}

func handleAppRefresh(task: BGAppRefreshTask) {
scheduleAppRefresh()

let db = Firestore.firestore()

db.collection("devices").document(UIDevice.current.identifierForVendor!.uuidString).setData([
"batteryLevel": UIDevice.current.batteryLevel*100
]) { err in
if let err = err {
print("Error writing document: (err)")
} else {
print("success")
task.setTaskCompleted(success: true)
}
}

task.expirationHandler = {
task.setTaskCompleted(success: false)
}
}

我正在运行

测试后台取回
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"redacted.identifier"]

在Xcode控制台中,之后出现上述错误。

控制台输出:

Simulating launch for task with identifier redacted.identifier
No task request with identifier <decode: missing data> has been scheduled

几个潜在的问题:

  • 在模拟器上测试时会发生这种情况。使用物理设备

  • 确保您的Info.plist有一个"允许的后台任务调度程序标识符"(即BGTaskSchedulerPermittedIdentifiers)条目与您的后台任务的标识符。

  • 确保在BGTaskScheduler.shared.submit(...)行之后立即设置断点,并且在调用submit之后执行_simulateLaunchForTaskWithIdentifier。例如,确保您甚至到达submit调用。(见下一点)

  • 值得注意的是,苹果的例子(和你的例子)在applicationDidEnterBackground(_:)中调度它。但是如果你使用的是UIWindowSceneDelegate(即在你的SceneDelegate中),那么应用程序委托的applicationDidEnterBackground(_:)不会被调用,而是场景委托的sceneDidEnterBackground(_:)被调用。我把BGAppRefreshTaskRequest的调度放在场景委托的sceneDidEnterBackground(_:)中。

我在设备上测试时也遇到了同样的问题。转到设备设置>一般比;后台应用刷新并打开后台应用刷新。

还有一种情况没有在其他答案中提到,如果您试图提交不同或多个刷新任务,您可能会遇到下面的错误情况。问题是,目前提到的错误没有在Xcode 13.1中抛出,所以它看起来像提交请求工作,但基本上它没有。

苹果医生:可同时安排1个刷新任务和10个处理任务。尝试调度更多任务返回BGTaskScheduler.Error.Code.tooManyPendingTaskRequests.

看起来applicationDidEnterBackground永远不会被调用,检查一下(添加断点)

func applicationDidEnterBackground(_ application: UIApplication) {
BGTaskScheduler.shared.cancelAllTaskRequests()
scheduleAppRefresh()
}

因为基于场景的配置生命周期

如果为真,将逻辑移到SceneDelegate类

func sceneDidEnterBackground(_ scene: UIScene) {
BGTaskScheduler.shared.cancelAllTaskRequests()
scheduleAppRefresh()
}

最新更新