ios swift请求框架_Swift iOS BackgroundTasks框架-只需4个步骤即可刷新后台应用程序

转载自:ios swift请求框架_Swift iOS BackgroundTasks框架-只需4个步骤即可刷新后台应用程序_weixin_26737625的博客-CSDN博客

e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"list.calendar.BackgroundAppRefreshIdentifier"]

ios swift请求框架

 

IOS allows app to refresh it content even when it is sent to background. iOS can intelligently study the user’s behaviour and schedule background tasks to the moment right before routine usage. It is useful for app to retrieve the latest information from its server and display to user right when app is resumed to foreground. Examples are social media app (Facebook, Instagram & WhatsApp) and news app.

I OS允许应用程序刷新内容,即使将其发送到后台也是如此。 iOS可以智能地研究用户的行为并将后台任务安排在常规使用之前的时刻。 当应用程序恢复到前台时,它对于从其服务器检索最新信息并向用户显示权限很有用。 例如社交媒体应用程序(Facebook,Instagram和WhatsApp)和新闻应用程序。

Image for post

illustration of foreground and background task; Copy from WWDC 2019 presentation slide 前台和后台任务的插图; 从WWDC 2019演示幻灯片中复制

Since iOS 13, Apple has added a new framework — BackgroundTasks — to handle the background task request between iOS and app side. BGAppRefreshTask & BGProcessingTask are the two available types of background task. BGAppRefreshTask can have 30 seconds to complete its job and BGProcessingTask can have more than a minute. The handling method is different for the old application(_:performFetchWithCompletionHandler:) way.

从iOS 13开始,Apple添加了一个新框架-BackgroundTasks-处理iOS和应用程序端之间的后台任务请求。 BGAppRefreshTaskBGProcessingTask是后台任务的两种可用类型。 BGAppRefreshTask可以有30秒完成工作,而BGProcessingTask可以有超过一分钟的时间 。 对于旧的应用程序(_:performFetchWithCompletionHandler :) ,处理方法有所不同。

Background task execution depends on several conditions, including:

后台任务的执行取决于多种条件,包括:

  1. User permission on “Background App Refresh”

    用户对“后台应用程序刷新”的权限
  2. Power supply from charger

    充电器供电
  3. Network connectivity

    网络连接

Let’s see how to setup the Background App Refresh and understand the details on using it!

让我们看看如何设置“后台应用刷新”并了解使用它的详细信息!


后台应用程序刷新的4个步骤 (4 Steps to Background App Refresh)


步骤1)为应用程序目标启用后台模式 (Step 1) Enable Background Modes for app target)

Go to the “Background Modes” session of the app target and check “Background fetch” and “Background processing” options if BGAppRefreshTask and BGProcessingTask are used respectively.

如果分别使用了BGAppRefreshTaskBGProcessingTask ,请转到应用程序目标的“ 后台模式 ”会话,并选中“ 后台获取 ”和“ 后台处理 ”选项。

Image for post

Capability session of app target 应用目标的功能会话


步骤2)添加“ 允许的后台任务计划程序标识符 ” (Step 2) Add “Permitted background task scheduler identifiers”)

Go to info.plist and add “Permitted background task scheduler identifiers” property with identifiers for BGAppRefreshTaskRequest and BGProcessingTaskRequest.

转到info.plist并添加“ 允许的后台任务调度程序标识符 ”属性以及BGAppRefreshTaskRequestBGProcessingTaskRequest的标识符 。

Image for post

Property List mode 属性列表模式


步骤3)注册调度程序任务标识符 (Step 3) Register a scheduler task identifier)

Register a scheduler task to BGTaskScheduler with the identifier defined at the previous step and a completion handler which is executed when background task is triggered.

将调度程序任务注册到BGTaskScheduler ,该任务具有在上一步中定义的标识符以及在触发后台任务时执行的完成处理程序。

According to the official documentation, launch handlers for BGTaskRequest should be registered before the end of the app launch sequence, i.e. application(_:didFinishLaunchingWithOptions:).

根据官方文档 ,应在应用启动序列(即application(_:didFinishLaunchingWithOptions :))结束之前注册BGTaskRequest启动处理程序。

 
  1. class AppDelegate: UIResponder, UIApplicationDelegate {

  2. var window: UIWindow?

  3. func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

  4. // Register Background task here

  5. registerBackgroundTasks()

  6. return true

  7. }

  8. func registerBackgroundTasks() {

  9. // Declared at the "Permitted background task scheduler identifiers" in info.plist

  10. let backgroundAppRefreshTaskSchedulerIdentifier = "com.example.fooBackgroundAppRefreshIdentifier"

  11. let backgroundProcessingTaskSchedulerIdentifier = "com.example.fooBackgroundProcessingIdentifier"

  12. // Use the identifier which represents your needs

  13. BGTaskScheduler.shared.register(forTaskWithIdentifier: backgroundAppRefreshTaskSchedulerIdentifier, using: nil) { (task) in

  14. print("BackgroundAppRefreshTaskScheduler is executed NOW!")

  15. print("Background time remaining: \(UIApplication.shared.backgroundTimeRemaining)s")

  16. task.expirationHandler = {

  17. task.setTaskCompleted(success: false)

  18. }

  19. // Do some data fetching and call setTaskCompleted(success:) asap!

  20. let isFetchingSuccess = true

  21. task.setTaskCompleted(success: isFetchingSuccess)

  22. }

  23. }

  24. }

Duplicated registration of the same task identifier can cause iOS terminates the app!! The following is the error message:

重复注册相同的任务标识符可能导致iOS终止应用程序! 以下是错误消息:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Launch handler for task with identifier com.example.fooBackgroundAppRefreshIdentifier has already been registered'


步骤4)将BGTaskRequest提交给BGTaskScheduler (Step 4) Submit the BGTaskRequest to the BGTaskScheduler)

Submitting a BGTaskRequest can throw the following exceptions:

提交BGTaskRequest可能会引发以下异常:

  1. BGTaskSchedulerErrorCodeUnavailable

    BGTaskSchedulerErrorCodeUnavailable

    User has disabled “Background App Refresh” option at the app Settings page

    用户已在应用设置页面禁用了“后台应用刷新”选项

  2. BGTaskSchedulerErrorCodeTooManyPendingTaskRequests

    BGTaskSchedulerErrorCodeTooManyPendingTaskRequests

    There can be a total of 1 refresh task and 10 processing tasks scheduled at any time.

    随时可以安排总共1个刷新任务和10个处理任务。

  3. BGTaskSchedulerErrorCodeNotPermittedThe corresponding “Background fetch” or “Background processing” is not checked at the Background modes session of app capabilities.

    BGTaskSchedulerErrorCodeNotPermitted在应用程序功能的“后台模式”会话中未检查相应的“后台获取”“后台处理” 。

Here is the codes for BGAppRefreshTaskRequest:

这是BGAppRefreshTaskRequest的代码:

 
  1. class AppDelegate: UIResponder, UIApplicationDelegate {

  2. var window: UIWindow?

  3. func applicationDidEnterBackground(_ application: UIApplication) {

  4. submitBackgroundTasks()

  5. }

  6. func submitBackgroundTasks() {

  7. // Declared at the "Permitted background task scheduler identifiers" in info.plist

  8. let backgroundAppRefreshTaskSchedulerIdentifier = "com.example.fooBackgroundAppRefreshIdentifier"

  9. let timeDelay = 10.0

  10. do {

  11. let backgroundAppRefreshTaskRequest = BGAppRefreshTaskRequest(identifier: backgroundAppRefreshTaskSchedulerIdentifier)

  12. backgroundAppRefreshTaskRequest.earliestBeginDate = Date(timeIntervalSinceNow: timeDelay)

  13. try BGTaskScheduler.shared.submit(backgroundAppRefreshTaskRequest)

  14. print("Submitted task request")

  15. } catch {

  16. print("Failed to submit BGTask")

  17. }

  18. }

  19. }


模拟BGTask (Simulate a BGTask)

Waiting for iOS to trigger a BGTask is a tedious job during development since iOS control the exact trigger time of BGTask to optimise device performance. Therefore, Apple provides the following commands (simulateLaunchForTaskWithIdentifier & simulateExpirationForTaskWithIdentifier) for simulating and terminating a BGTask :

在iOS开发过程中,等待iOS触发BGTask的工作非常繁琐,因为iOS会控制BGTask的确切触发时间来优化设备性能。 因此,Apple提供了以下命令( simulateLaunchForTaskWithIdentifier  simulateExpirationForTaskWithIdentifier )来模拟和终止BGTask :

 
  1. // For BGTask with identifier "fooBackgroundAppRefreshIdentifier"

  2. e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@“com.example.fooBackgroundAppRefreshIdentifier"]

  3. // For BGTask with identifier "fooBackgroundProcessingIdentifier"

  4. e -l objc - (void)[[BGTaskScheduler sharedScheduler] _simulateExpirationForTaskWithIdentifier:@"com.example.fooBackgroundProcessingIdentifier"]

The commands are not Swift codes and can only be executed at the Xcode Terminal. Follow the steps shown below to trigger a BGTask in Xcode:

这些命令不是Swift代码,只能在Xcode终端上执行。 请按照以下所示的步骤在Xcode中触发BGTask :


步骤1:在将BGTask提交给BGTaskScheduler后,随时暂停应用 (Step 1: Pause app at any point after submitting the BGTask to BGTaskScheduler)

Image for post


步骤2:在Xcode的终端上运行命令 (Step 2: Run the command at the Terminal in Xcode)

Image for post


步骤3:恢复您的应用 (Step 3: Resume back your app)

You can see the completion handler of the registered BGTask is then triggered.

您可以看到注册的BGTask的完成处理程序随后被触发。

Image for post


BGAppRefreshTask与BGProcessingTask (BGAppRefreshTask Vs BGProcessingTask)

 
  1. BGTaskScheduler.shared.register(forTaskWithIdentifier: backgroundProcessingTaskSchedulerIdentifier, using: nil) { (task) in

  2. print("BackgroundProcessingTaskScheduler is executed NOW!")

  3. DispatchQueue.main.asyncAfter(deadline: .now() + 1) {

  4. print("Time remaining: \(UIApplication.shared.backgroundTimeRemaining)")

  5. }

  6. task.expirationHandler = {

  7. task.setTaskCompleted(success: false)

  8. }

  9. // Do some time-consuming tasks

  10. task.setTaskCompleted(success: true)

  11. }


Property: expirationHandler (Property: expirationHandler)

The most important property of BGTask is the expirationHandler. It is a callback that iOS will call when the BGTask has to be terminated by system due to time out or other issues.

BGTask的最重要属性是expirationHandler 。 当由于超时或其他问题而必须由系统终止BGTask时,iOS将调用此回调。


函数:setTaskCompleted(成功:) (Function: setTaskCompleted(success: ))

This is an important function and informs the background task scheduler that the task is complete. Developer should call this function as soon as possible since extra battery power is consumed and iOS would suspends the app as soon as all background tasks are complete!

这是一项重要功能,它会通知后台任务计划程序任务已完成。 开发人员应尽快调用此函数,因为会消耗额外的电池电量,并且一旦所有后台任务完成,iOS就会暂停该应用程序!


比较:用法 (Comparison: Usage)

BGAppRefreshTask is chosen for updating small bits of information, e.g. getting the latest stock price and news from server. The duration is limited to around 30s after sending to background.

选择BGAppRefreshTask用于更新少量信息,例如从服务器获取最新股价和新闻。 发送到后台后,持续时间限制为30秒左右。

BGProcessingTask is used when performing a time-consuming processing. The time for BGProcessingTask can be up to minutes! However, processing tasks run only when the device is idle. The system terminates any background processing tasks running when the user starts using the device. Background refresh tasks are not affected. Therefore, it is necessary to set the expirationHandler for the BGTask object introduced at the previous section.The system will attempt to fulfil this request to the best of its ability within the next two days as long as the user has used your app within the past week.

在执行耗时的处理时使用BGProcessingTask 。 BGProcessingTask的时间可能长达几分钟 ! 但是,处理任务仅在设备空闲时运行。 当用户开始使用设备时,系统将终止正在运行的所有后台处理任务。 后台刷新任务不受影响。 因此,有必要为上一BGTask介绍的BGTask对象设置expirationHandler 。只要用户在过去使用过您的应用,系统将尝试在接下来的两天内尽力满足此请求。周。


BGAppRefreshTaskRequest和BGProcessingTaskRequest (BGAppRefreshTaskRequest and BGProcessingTaskRequest)


通用字段) earliestBeginDate (Common field) earliestBeginDate)

It indicates the earliest date that this task should be executed. However, earliest date does not equal exact date. iOS does not guarantee the task will begin at the earliest date and can delay the background task for power optimisation and app usage pattern.

它指示该任务应最早执行的日期。 但是, 最早的日期不等于确切的日期 。 iOS无法保证该任务最早开始,并且可以延迟后台任务进行电源优化和应用使用模式。


BGProcessingTaskRequest —配置1)requireNetworkConnectivity (BGProcessingTaskRequest — Configuration 1) requiresNetworkConnectivity)

Indicate if this background process requires network connectivity. Default value is false.

指示此后台进程是否需要网络连接。 默认值为false。


BGProcessingTaskRequest-配置2)requireExternalPower (BGProcessingTaskRequest — Configuration 2) requiresExternalPower)

Indicate if this background process requires the device to connect to an external power. This is set to true only when the task is resource intensive to minimise impact to battery life.

指示此后台进程是否要求设备连接到外部电源。 仅当任务占用大量资源以最大程度地减少对电池寿命的影响时,才将其设置为true。


监控后台应用刷新授权 (Monitor Background App Refresh authorization)

Image for post

User has the final privilege to enable / disable the “Background App Refresh” even both network and battery situation are at good level. Developer should monitor the corresponding authorization and redirect user to Settings app if background app refresh is a critical feature.

即使网络和电池电量都处于良好水平,用户也具有启用/禁用“ Background App Refresh”的最终特权。 如果后台应用刷新是一项关键功能,则开发人员应监视相应的授权并将用户重定向到“设置”应用。

 
  1. func checkBackgroundRefreshStatus() {

  2. switch UIApplication.shared.backgroundRefreshStatus {

  3. case .available:

  4. print("Background fetch is enabled")

  5. case .denied:

  6. print("Background fetch is explicitly disbaled")

  7. // Redirect user to Settings page only once; Respect user's choice is important

  8. UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)

  9. case .restricted:

  10. // Should not redirect user to Settings since he / she cannot toggle the settings

  11. print("Background fetch is restricted, e.g. under parental control")

  12. default:

  13. print("Unknown property")

  14. }

  15. }

We can use UIApplication.shared.backgroundRefreshStatus to get the current authorization status of Background App Refresh. There are three possible values:

我们可以使用UIApplication.shared.backgroundRefreshStatus来获取Background App Refresh的当前授权状态。 有三个可能的值:

  1. available —User has enable the Background App Refresh feature. This is the default value when app is first installed.

    available用户已启用“后台应用刷新”功能。 这是首次安装应用程序时的默认值。

  2. denied — User has explicitly disabled the Background App Refresh feature. We can redirect user to the app settings page to toggle back the status with code UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!) .

    denied -用户已明确禁用后台应用刷新功能。 我们可以将用户重定向到应用设置页面,以使用代码UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)切换回状态。

  3. restrict — User is not able to toggle the background refresh status due to his account restriction, e.g. parental control

    restrict -由于帐户限制(例如,家长控制),用户无法切换后台刷新状态


监视授权状态的更改 (Monitoring the change of authorization status)

 
  1. class FooViewController: UIViewController {

  2. override func viewDidLoad() {

  3. super.viewDidLoad()

  4. NotificationCenter.default.addObserver(

  5. self,

  6. selector: #selector(backgroundRefreshStatusDidChange),

  7. name: UIApplication.backgroundRefreshStatusDidChangeNotification, object: nil)

  8. }

  9. @objc

  10. func backgroundRefreshStatusDidChange(notification: NSNotification) {

  11. print("New status: \(UIApplication.shared.backgroundRefreshStatus)")

  12. }

  13. }

After user has changed the Background App Refresh status, app can be notified by observing the UIApplication.backgroundRefreshStatusDidChangeNotification notification. This can be used to show any pop up dialog to user to explain the usage and importance of Background App Refresh to the app flow.

用户更改了后台应用程序刷新状态后,可以通过观察UIApplication.backgroundRefreshStatusDidChangeNotification通知来通知应用程序。 这可用于向用户显示任何弹出对话框,以说明Background App Refresh对应用流的用法和重要性。


摘要 (Summary)

  1. Background task can only be executed when user enables “Background App Refresh”.

    仅当用户启用“后台应用刷新”时,才能执行后台任务。
  2. Background task identifier must be added to “Permitted background task scheduler identifiers” field in the info.plist

    必须将后台任务标识符添加到info.plist “ 允许的后台任务调度程序标识符”字段中

  3. BGAppRefreshTask can has 30s and BGProcessingTask has more than 1 minute to complete its background task.

    BGAppRefreshTask可以有30到BGProcessingTask拥有超过1分钟内完成其后台任务。

  4. There can be a total of 1 refresh task and 10 processing tasks scheduled at any time.

    随时可以安排总共1个刷新任务和10个处理任务。
  5. Registration of task identifier should be done before app finishes launch with options application(_:didFinishLaunchingWithOptions:)

    任务标识符的注册应在应用程序通过选项application(_:didFinishLaunchingWithOptions :)启动完成之前完成

  6. Duplicated registration of the same task identifier can cause iOS terminate you app.

    同一任务标识符的重复注册可能导致iOS终止您的应用。
  7. Triggered background task cannot be triggered again in the future. It must be resubmitted / rescheduled again.

    触发的后台任务将来无法再次触发。 必须重新提交/重新安排。


您可能喜欢的东西: (Things you probably like:)

If you have to support user with device running in iOS 12 or below, use the application(_:performFetchWithCompletionHandler:) with setMinimumBackgroundFetchInterval(:_) instead. You can find more information here below:

如果必须使用在iOS 12或更低版本中运行的设备来支持用户,请改用具有setMinimumBackgroundFetchInterval(:_)application(_:performFetchWithCompletionHandler :) 。 您可以在下面找到更多信息:


参考和进一步阅读: (Reference & Further readings:)

1. Sample code of WWDC 2019 session 707: Advances in App Background Execution.

1. WWDC 2019会议707的示例代码:App Background Execution的进展 。

2. BackgroundTasks framework official documentation

2. BackgroundTasks框架官方文档

Background Tasks | Apple Developer Documentation

后台任务| Apple开发人员文档

You are welcome to follow me at Twitter@myrick_chow for more information and articles. Thank you for reading this article. Have a nice day! 😄

欢迎您通过Twitter @ myrick_chow关注我,以获取更多信息和文章。 感谢您阅读本文。 祝你今天愉快! 😄

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值