跳到主要内容

后台任务

问题

iOS 后台执行有哪些方式和限制?

答案

Background Modes

在 Xcode Capabilities 中启用:

Mode用途
Audio后台音频播放
Location updates后台定位
Background fetch定时拉取数据
Remote notifications静默推送触发任务
Background processingiOS 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 只是最早时间,实际可能延迟数小时。

相关链接