注册的 BGTaskScheduler 任务未运行 launchHandler

问题描述 投票:0回答:1

我正在尝试使用

BGTaskScheduler.shared.register(identifier:queue:launchHandler:)
安排后台任务在后台运行,但
launchHandler
块永远不会执行。

我尝试过的:

  • 我在模拟器和物理设备上都尝试过。
  • 我已启用后台模式(后台获取)。
  • 并已使用
    SceneDelegate
    sceneDidEnterBackground(:)
    BGTaskScheduler.shared.submit(:)
    提交任务。
  • 我还在
    Info.plist
    中将标识符添加到“允许的后台任务调度程序标识符”中。
  • 我尝试过选择
    Debug > Simulate Background Fetch

这是我的代码:

func scene(_ scene: UIScene,
           willConnectTo session: UISceneSession,
           options connectionOptions: UIScene.ConnectionOptions) {        
    let isRegistered = BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.bgTaskIdentifier",
                                                       using: nil) { task in
        print("Executed") // Does not print
        self.handleAppRefresh(task: task as! BGAppRefreshTask)
    }
    
    print("isRegistered: \(isRegistered)") // Prints "isRegistered: true"
}


func sceneDidEnterBackground(_ scene: UIScene) {
    scheduleAppRefresh()
    print("Entered Background") // Prints "Entered Background"
}

func scheduleAppRefresh() {
    let request = BGAppRefreshTaskRequest(identifier: "com.example.bgTaskIdentifier")
    request.earliestBeginDate = Date(timeIntervalSinceNow: 5 * 60)
    
    do {
        try BGTaskScheduler.shared.submit(request)
    } catch {
        print("Could not schedule app refresh: \(error)") // Does not reach the catch block
    }
}

ios swift swiftui bgtaskscheduler
1个回答
0
投票

两个观察:

  1. 当我在模拟器上运行此程序时,当我点击

    BGTaskScheduler.shared.submit(request)
    时,它会抛出
    BGTaskScheduler.Error.invalid
    错误,其文档告诉我们,如果出现以下情况,就会发生这种情况:

    该应用程序在模拟器上运行,不支持后台处理。

  2. 当我在实际设备上运行它时,我等待“已进入后台”消息,然后暂停执行,然后在

    (lldb)
    提示符处输入:

    e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.example.bgTaskIdentifier"]
    

    然后点击“继续执行”按钮,然后调用我的

    handleAppRefresh(task:)
    方法。

    此调试过程在开发期间启动和终止任务

    中进行了概述

无论如何,这是我的完整内容

SceneDelegate

import UIKit
import os.log
import BackgroundTasks

// MARK: - SceneDelegate

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "SceneDelegate")
    var window: UIWindow?

    func scene(
        _ scene: UIScene,
        willConnectTo session: UISceneSession,
        options connectionOptions: UIScene.ConnectionOptions
    ) {
        let isRegistered = BGTaskScheduler.shared.register(
            forTaskWithIdentifier: "com.example.bgTaskIdentifier",
            using: nil
        ) { task in
            self.logger.debug("Executed") // Does not print
            self.handleAppRefresh(task: task as! BGAppRefreshTask)
        }

        logger.debug("isRegistered: \(isRegistered)") // Prints "isRegistered: true"
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        scheduleAppRefresh()
        logger.debug("Entered Background") // Prints "Entered Background"
    }
}

// MARK: - Private utility methods

private extension SceneDelegate {
    func scheduleAppRefresh() {
        let request = BGAppRefreshTaskRequest(identifier: "com.example.bgTaskIdentifier")
        request.earliestBeginDate = Date(timeIntervalSinceNow: 5 * 60)

        do {
            try BGTaskScheduler.shared.submit(request)
        } catch {
            logger.error("Could not schedule app refresh: \(error)") // Does not reach the catch block
        }
    }

    func handleAppRefresh(task: BGAppRefreshTask) {
        logger.debug("starting \(#function)")

        scheduleAppRefresh() // make sure to schedule again, so that this continues to enjoy future background fetch

        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            task.setTaskCompleted(success: true)
            self.logger.debug("finishing \(#function)")
        }
    }
}

// MARK: - BGTaskScheduler.Error: CustomStringConvertible

extension BGTaskScheduler.Error: CustomStringConvertible {
    public var description: String {
        return switch code {
        case .notPermitted:               "notPermitted"
        case .tooManyPendingTaskRequests: "tooManyPendingTaskRequests"
        case .unavailable:                "unavailable"
        default:                          "default"
        }
    }
}

当我执行上述过程(暂停,lldb 命令,然后继续”)时,我在控制台上看到以下内容:

scene(_:willConnectTo:options:): isRegistered: true
sceneDidEnterBackground(_:)
scheduleAppRefresh()

然后我点击“暂停程序执行”按钮,然后出现

(lldb)
提示:

(lldb) e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.example.bgTaskIdentifier"]
Executed

然后点击“继续程序执行”按钮,然后我在控制台中看到以下内容:

starting handleAppRefresh(task:)
scheduleAppRefresh()
finishing handleAppRefresh(task:)
© www.soinside.com 2019 - 2024. All rights reserved.