BGAppRefreshTask 不执行 SwiftUI

BGAppRefreshTask not executing SwiftUI

我在使用 SwiftUI 编写的应用程序的 Background Tasks 框架时得到不一致的结果。我只想快速发出网络请求,所以我选择使用 BGAppRefreshTask.

后台提取和后台处理在签名和功能中设置。已设置允许的后台任务计划程序标识符。在调试中手动调用它在真实设备上工作正常但在生产中却不行。

我测试了 BGAppRefreshTaskBGProcessingTask。我注意到正在调用 BGProcessingTask,但仅在连接到电源时才调用。我从来没有看到 BGAppRefreshTask 的任何更新。我不确定我是否遗漏了一些简单的东西。

BGAppRefreshTask 运行 4 天 自从更新这个 post 以来。 BGProcessingTask 一夜之间 运行 13 次,但前提是我的设备正在充电。即使将 requiresExternalPower 设置为 false.

BGAppRefreshTask run: 0 & BGProcessingTask run: 13

使用命令 here 在调试器中调用是可行的,但如果不在调试器中进行模拟,它永远不会 运行 在我的设备上。

(lldb) e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.bgapp.refresh"]
2022-02-26 11:41:33.964753-0800 BGAppRefreshTask[9180:2203525] Simulating launch for task with identifier com.bgapp.refresh
2022-02-26 11:41:35.908739-0800 BGAppRefreshTask[9180:2203542] Starting simulated task: <decode: missing data>
2022-02-26 11:41:35.912108-0800 BGAppRefreshTask[9180:2203542] Marking simulated task complete: <BGAppRefreshTask: com.bgapp.refresh>
Received completion: finished.

更新

我使用 getPendingTaskRequests 查看是否有任何任务正在注册,很明显它正在但仍未执行。最早的日期安排在 19:28,所以 7:28PM。我在 11:23AM 注册了我的任务,但它没有安排 运行 再 8 小时 .

Pending task requests: [<BGAppRefreshTaskRequest: com.bgapp.refresh, earliestBeginDate: 2022-02-28 19:28:34 +0000>]

BGAppRefresh

/*!
 BGAppRefreshTask
 @abstract A background task used to update your app's contents in the background.
 */
class BGADelegate: NSObject,  UIApplicationDelegate, ObservableObject {
    let taskIdentifier = "com.bgapp.refresh"
    @AppStorage("backgroundtask") var tasks: Int = 0
    
    func application(_ applicatiown: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        register()
        scheduleAppRefresh()
        return true
    }

    func register() {
        BGTaskScheduler.shared.register(forTaskWithIdentifier: taskIdentifier, using: nil) { task in
            self.handleAppRefresh(task: task as! BGAppRefreshTask)
            print("register")
        }
    }
    
    func scheduleAppRefresh() {
        let request = BGAppRefreshTaskRequest(identifier: taskIdentifier)
        request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
        do {
            try BGTaskScheduler.shared.submit(request)
        } catch {
            print("Could not schedule app refresh: \(error)")
        }
    }
    
    func handleAppRefresh(task: BGAppRefreshTask) {
        scheduleAppRefresh()
        task.expirationHandler = {
            task.setTaskCompleted(success: false)
        }
        DispatchQueue.main.async {
            self.tasks += 1
        }
        // Network request here
        task.setTaskCompleted(success: true)
        print("handle app refresh")
    }
    
}

BGProcessingTask

/*!
 BGProcessingTask
 @abstract A background task used to perform deferrable processing.
 */
class BGPDelegate: NSObject,  UIApplicationDelegate, ObservableObject {
    let taskIdentifier = "com.bgapp.refresh"
    @AppStorage("backgroundtask") var tasks: Int = 0
    
    func application(_ applicatiown: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        register()
        scheduleAppRefresh()
        return true
    }

    func register() {
        BGTaskScheduler.shared.register(forTaskWithIdentifier: taskIdentifier, using: nil) { task in
            self.handleAppRefresh(task: task as! BGProcessingTask)
            print("register")
        }
    }
    
    func scheduleAppRefresh() {
        let request = BGProcessingTaskRequest(identifier: taskIdentifier)
        request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
        request.requiresNetworkConnectivity = true
        request.requiresExternalPower = false // Default value in false
        do {
            try BGTaskScheduler.shared.submit(request)
        } catch {
            print("Could not schedule app refresh: \(error)")
        }
    }
    
    func handleAppRefresh(task: BGProcessingTask) {
        scheduleAppRefresh()
        task.expirationHandler = {
            task.setTaskCompleted(success: false)
        }
        DispatchQueue.main.async {
            self.backgroundtask += 1
        }
        // Network request here
        task.setTaskCompleted(success: true)
        print("handle app refresh")
    }
    
}

所以根据对 Background Tasks 的新理解,我现在知道它被安排在最早的日期,但我打开应用程序设置了它的预定日期。我没有等到重新启动应用程序时预定的较早日期。设置后台应用刷新任务时,每个任务都会被覆盖

struct BGAppRefreshTaskApp: App {
    @UIApplicationDelegateAdaptor var delegate: AppDelegate
    @Environment(\.scenePhase) var scenePhase
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(delegate)
                .onChange(of: scenePhase) { phase in
                    switch phase {
                    case .background:
                        delegate.scheduleAppRefresh()
                        delegate.background += 1
                        print("background")
                    case .active:
                        print("active")
                        BGTaskScheduler.shared.getPendingTaskRequests(completionHandler: { request in
                            print("Pending task requests: \(request)")
                        })
                    case .inactive:
                        print("inactive")
                    @unknown default:
                        break
                    }
                }
        }
    }
}