参考: Choosing Background Strategies for Your App
- 进入后台,继续执行前台未完成的任务
- 后台上传下载文件
- 推迟高强度工作
- 更新应用内容
- 用后台推送唤醒你的应用
- 其他后台模式
进入后台,继续前台任务
SDWebImage 采用这种方式,进入后台继续下载图片,下载完成后结束后台任务。如果后台时间用尽, 下载未完成,则取消下载。
- (void)registerTask {
//注册一个后台任务
__weak typeof(self)weakself = self;
self.taskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"test" expirationHandler:^{
//任务到期后需要调用 endBackgroundTask
[weakself cancel];
}];
/*
... 耗时任务开始
进入后台后,继续执行一段时间。
后台时间耗尽前,执行成功,调用 taskDone 结束后台任务
后台任务耗尽,任务没有执行成功, 回调 expirationHandler,取消耗时工作,结束后台任务
*/
}
//耗时工作结束,告诉系统后台任务完成
- (void)taskDone {
[[UIApplication sharedApplication] endBackgroundTask:self.taskIdentifier];
self.taskIdentifier = UIBackgroundTaskInvalid;
}
//后台时间被用完,取消耗时任务
- (void)cancel {
/*
... 取消耗时任务, 一些清理
*/
if (self.taskIdentifier != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:self.taskIdentifier];
self.taskIdentifier = UIBackgroundTaskInvalid;
}
}
后台上传下载文件
Downloading Files in the Background
创建后台sesson
private lazy var urlSession: URLSession = {
let config = URLSessionConfiguration.background(withIdentifier: "MySession")
config.isDiscretionary = true
config.sessionSendsLaunchEvents = true
return URLSession(configuration: config, delegate: self, delegateQueue: nil)
}()
创建后台上传/下载任务
let backgroundTask = urlSession.downloadTask(with: url)
backgroundTask.earliestBeginDate = Date().addingTimeInterval(60 * 60)
backgroundTask.countOfBytesClientExpectsToSend = 200
backgroundTask.countOfBytesClientExpectsToReceive = 500 * 1024
backgroundTask.resume()
如果应用在后台,你的应用会被挂起,系统在另外的进程进行下载,下载完成之后,唤醒你的app, 通知处理下载结束,用户保存completionHandler,
开始处理下载结果,处理完成调用 completionHandler 告诉系统结束对下载内容的处理。
func application(_ application: UIApplication,
handleEventsForBackgroundURLSession identifier: String,
completionHandler: @escaping () -> Void) {
backgroundCompletionHandler = completionHandler
}
处理下载结果
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
DispatchQueue.main.async {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate,
let backgroundCompletionHandler =
appDelegate.backgroundCompletionHandler else {
return
}
backgroundCompletionHandler()
}
}
后台更新应用内容
参考 Using Background Tasks to Update Your App
-
注册后台模式
image.png
- info.plist 添加后台任务id数组
BGTaskSchedulerPermittedIdentifiers
image.png
- 注册任务
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.apple-samplecode.ColorFeed.refresh", using: nil) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
- 提交任务
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "com.example.apple-samplecode.ColorFeed.refresh")
// Fetch no earlier than 15 minutes from now.
request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh: \(error)")
}
}
- 任务触发
func handleAppRefresh(task: BGAppRefreshTask) {
// Schedule a new refresh task.
scheduleAppRefresh()
// Create an operation that performs the main part of the background task.
let operation = RefreshAppContentsOperation()
// Provide the background task with an expiration handler that cancels the operation.
task.expirationHandler = {
operation.cancel()
}
// Inform the system that the background task is complete
// when the operation completes.
operation.completionBlock = {
task.setTaskCompleted(success: !operation.isCancelled)
}
// Start the operation.
operationQueue.addOperation(operation)
}
网友评论