我正在尝试使用
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
}
}
两个观察:
当我在模拟器上运行此程序时,当我点击
BGTaskScheduler.shared.submit(request)
时,它会抛出 BGTaskScheduler.Error.invalid
错误,其文档告诉我们,如果出现以下情况,就会发生这种情况:
该应用程序在模拟器上运行,不支持后台处理。
当我在实际设备上运行它时,我等待“已进入后台”消息,然后暂停执行,然后在
(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:)