后台任务
问题
iOS 后台执行有哪些方式和限制?
答案
Background Modes
在 Xcode Capabilities 中启用:
| Mode | 用途 |
|---|---|
| Audio | 后台音频播放 |
| Location updates | 后台定位 |
| Background fetch | 定时拉取数据 |
| Remote notifications | 静默推送触发任务 |
| Background processing | iOS 13+ 后台处理 |
BGTaskScheduler(iOS 13+)
import BackgroundTasks
// 1. Info.plist 注册
// BGTaskSchedulerPermittedIdentifiers: ["com.app.refresh", "com.app.dbCleanup"]
// 2. 注册处理器(在 didFinishLaunching 中)
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.app.refresh", using: nil) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.app.dbCleanup", using: nil) { task in
self.handleDbCleanup(task: task as! BGProcessingTask)
}
// 3. 调度任务
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "com.app.refresh")
request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // 最早 15 分钟后
try? BGTaskScheduler.shared.submit(request)
}
// 4. 处理任务
func handleAppRefresh(task: BGAppRefreshTask) {
scheduleAppRefresh() // 重新调度下一次
let operation = RefreshOperation()
task.expirationHandler = { operation.cancel() }
operation.completionBlock = {
task.setTaskCompleted(success: !operation.isCancelled)
}
OperationQueue().addOperation(operation)
}
短时后台任务
// 进入后台时申请额外执行时间(约 30 秒)
func sceneDidEnterBackground(_ scene: UIScene) {
var taskId: UIBackgroundTaskIdentifier = .invalid
taskId = UIApplication.shared.beginBackgroundTask {
// 时间到,必须结束
UIApplication.shared.endBackgroundTask(taskId)
taskId = .invalid
}
// 执行保存等操作
saveData()
UIApplication.shared.endBackgroundTask(taskId)
taskId = .invalid
}
常见面试问题
Q1: 后台任务一定会执行吗?
答案:不一定。BGTaskScheduler 的任务由系统根据电量、网络、使用模式等条件智能调度,earliestBeginDate 只是最早时间,实际可能延迟数小时。