我是第一次尝试iOS后台任务。 按照示例 WWDC'19 代码,我设置了一个简单的应用程序,该应用程序在ViewController.viewDidLoad()
中将UserDefaults
键的值设置为 1,并在后台任务中将其设置为 2。 我在进入背景之前和返回前景时打印了值。 该值始终打印为 1,即使让应用在后台放置一夜也是如此。我的后台任务未运行吗? 或者可能是我的UserDefaults
值在前台和后台任务之间没有同步,如几个堆栈溢出问题中所讨论的那样?还是我做错了什么? 任何指针都值得赞赏。
我已经检查了"签名和功能"下的"后台模式"中的"后台获取"项,并且我还在Info.plist
中的"允许的后台任务计划程序"下将"com.example.BGTask.refresh"添加为"第0项"。我正在设备上运行该应用程序,并连接到Xcode。
iOS 13.5.1, Xcode 11.5
应用委托.swift:
import UIKit
import BackgroundTasks
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.BGTask.refresh", using: nil) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
return true
}
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "com.example.BGTask.refresh")
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)
}
UserDefaults.standard.set(2, forKey: "bgtask")
task.setTaskCompleted(success: true)
}
// MARK: UISceneSession Lifecycle
// rest of templated AppDelegate.swift
SceneDelegate.swift:在本教程之后,我在SceneDelegate
中调用scheduleAppRefresh()
而不是AppDelegate
,并修改了这两个函数:
func sceneDidBecomeActive(_ scene: UIScene) {
print("didBecomeActive: ", UserDefaults.standard.integer(forKey: "bgtask"))
}
func sceneDidEnterBackground(_ scene: UIScene) {
print("didEnterBackground: ", UserDefaults.standard.integer(forKey: "bgtask"))
(UIApplication.shared.delegate as! AppDelegate).scheduleAppRefresh()
}
最后,在ViewController.swift:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
UserDefaults.standard.set(1, forKey: "bgtask")
print("viewDidLoad: ", UserDefaults.standard.integer(forKey: "bgtask"))
}
}
这是我在Xcode控制台上打印出来的:
viewDidLoad: 1
didBecomeActive: 1
// tap the Home button
didEnterBackground: 1
// after a suitably long time, tap the app icon
didBecomeActive: 1
为什么UserDefaults.shared.integer(forKey: "bgtask")
没有递增第二个didBecomeActive
?
在我看完 wwdc2019 之后
https://developer.apple.com/videos/play/wwdc2019/707/
仅当系统决定这样做时,才会执行任务
您也可以查看此论坛讨论链接:
https://forums.developer.apple.com/thread/124320
好吧,我让后台处理工作。 Xcode 控制台输出:
viewDidLoad: 1
didBecomeActive: 1
didEnterBackground: 1
didBecomeActive: 1
didEnterBackground: 1
// after about 15 minutes
didBecomeActive: 2
didEnterBackground: 2
// after staying in background overnight (~8 hours)
didBecomeActive: 19
didEnterBackground: 19
我没有勾选"后台获取",而是在"签名和功能"下的"后台模式"中勾选了"后台处理"。
应用委托.swift:
import UIKit
import BackgroundTasks
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.BGTask.refresh", using: nil) { task in
self.handleAppRefresh(task: task as! BGProcessingTask)
}
return true
}
func scheduleAppRefresh() {
let request = BGProcessingTaskRequest(identifier: "com.example.BGTask.refresh")
request.requiresNetworkConnectivity = false
request.requiresExternalPower = 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)
}
// increment instead of a fixed number
UserDefaults.standard.set(UserDefaults.standard.integer(forKey: "bgtask")+1, forKey: "bgtask")
task.setTaskCompleted(success: true)
}
// MARK: UISceneSession Lifecycle
// rest of templated AppDelegate.swift
并且没有对其他文件进行其他更改。
现在,为什么BGProcessing可以工作,而BGAppRefresh却不能呢?