iOS后台模式策略选择

2021-11-15  本文已影响0人  yxibng

参考: Choosing Background Strategies for Your App

  1. 进入后台,继续执行前台未完成的任务
    • 后台上传下载文件
  2. 推迟高强度工作
  3. 更新应用内容
  4. 用后台推送唤醒你的应用
  5. 其他后台模式

进入后台,继续前台任务

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

  1. 注册后台模式


    image.png
  2. info.plist 添加后台任务id数组 BGTaskSchedulerPermittedIdentifiers
    image.png
  3. 注册任务
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.apple-samplecode.ColorFeed.refresh", using: nil) { task in
     self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
  1. 提交任务
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)")
   }
}
  1. 任务触发
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)
 }

后台推送唤醒

其他后台模式

上一篇 下一篇

猜你喜欢

热点阅读