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)和新闻应用程序。

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和应用程序端之间的后台任务请求。 BGAppRefreshTask和BGProcessingTask是后台任务的两种可用类型。 BGAppRefreshTask可以有30秒完成工作,而BGProcessingTask可以有超过一分钟的时间 。 对于旧的应用程序(_:performFetchWithCompletionHandler :) ,处理方法有所不同。
Background task execution depends on several conditions, including:
后台任务的执行取决于多种条件,包括:
- User permission on “Background App Refresh” 用户对“后台应用程序刷新”的权限
- Power supply from charger 充电器供电
- 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.
如果分别使用了BGAppRefreshTask和BGProcessingTask ,请转到应用程序目标的“ 后台模式 ”会话,并选中“ 后台获取 ”和“ 后台处理 ”选项。

步骤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
并添加“ 允许的后台任务调度程序标识符 ”属性以及BGAppRefreshTaskRequest和BGProcessingTaskRequest的标识符 。

步骤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
启动处理程序。
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Register Background task here
registerBackgroundTasks()
return true
}
func registerBackgroundTasks() {
// Declared at the "Permitted background task scheduler identifiers" in info.plist
let backgroundAppRefreshTaskSchedulerIdentifier = "com.example.fooBackgroundAppRefreshIdentifier"
let backgroundProcessingTaskSchedulerIdentifier = "com.example.fooBackgroundProcessingIdentifier"
// Use the identifier which represents your needs
BGTaskScheduler.shared.register(forTaskWithIdentifier: backgroundAppRefreshTaskSchedulerIdentifier, using: nil) { (task) in
print("BackgroundAppRefreshTaskScheduler is executed NOW!")
print("Background time remaining: \(UIApplication.shared.backgroundTimeRemaining)s")
task.expirationHandler = {
task.setTaskCompleted(success: false)
}
// Do some data fetching and call setTaskCompleted(success:) asap!
let isFetchingSuccess = true
task.setTaskCompleted(success: isFetchingSuccess)
}
}
}
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
可能会引发以下异常:
BGTaskSchedulerErrorCodeUnavailable
BGTaskSchedulerErrorCodeUnavailable
User has disabled “Background App Refresh” option at the app Settings page
用户已在应用设置页面禁用了“后台应用刷新”选项
BGTaskSchedulerErrorCodeTooManyPendingTaskRequests
BGTaskSchedulerErrorCodeTooManyPendingTaskRequests
There can be a total of 1 refresh task and 10 processing tasks scheduled at any time.
随时可以安排总共1个刷新任务和10个处理任务。
BGTaskSchedulerErrorCodeNotPermitted
The 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
的代码:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func applicationDidEnterBackground(_ application: UIApplication) {
submitBackgroundTasks()
}
func submitBackgroundTasks() {
// Declared at the "Permitted background task scheduler identifiers" in info.plist
let backgroundAppRefreshTaskSchedulerIdentifier = "com.example.fooBackgroundAppRefreshIdentifier"
let timeDelay = 10.0
do {
let backgroundAppRefreshTaskRequest = BGAppRefreshTaskRequest(identifier: backgroundAppRefreshTaskSchedulerIdentifier)
backgroundAppRefreshTaskRequest.earliestBeginDate = Date(timeIntervalSinceNow: timeDelay)
try BGTaskScheduler.shared.submit(backgroundAppRefreshTaskRequest)
print("Submitted task request")
} catch {
print("Failed to submit BGTask")
}
}
}
模拟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
:
// For BGTask with identifier "fooBackgroundAppRefreshIdentifier"
e -l objc - (void)[[BGTaskScheduler sharedScheduler] _simulateExpirationForTaskWithIdentifier:@"com.example.fooBackgroundAppRefreshIdentifier"]
// For BGTask with identifier "fooBackgroundProcessingIdentifier"
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)

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

步骤3:恢复您的应用 (Step 3: Resume back your app)
You can see the completion handler of the registered BGTask is then triggered.
您可以看到注册的BGTask的完成处理程序随后被触发。

BGAppRefreshTask与BGProcessingTask (BGAppRefreshTask Vs BGProcessingTask)
BGTaskScheduler.shared.register(forTaskWithIdentifier: backgroundProcessingTaskSchedulerIdentifier, using: nil) { (task) in
print("BackgroundProcessingTaskScheduler is executed NOW!")
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
print("Time remaining: \(UIApplication.shared.backgroundTimeRemaining)")
}
task.expirationHandler = {
task.setTaskCompleted(success: false)
}
// Do some time-consuming tasks
task.setTaskCompleted(success: true)
}
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)

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”的最终特权。 如果后台应用刷新是一项关键功能,则开发人员应监视相应的授权并将用户重定向到“设置”应用。
func checkBackgroundRefreshStatus() {
switch UIApplication.shared.backgroundRefreshStatus {
case .available:
print("Background fetch is enabled")
case .denied:
print("Background fetch is explicitly disbaled")
// Redirect user to Settings page only once; Respect user's choice is important
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
case .restricted:
// Should not redirect user to Settings since he / she cannot toggle the settings
print("Background fetch is restricted, e.g. under parental control")
default:
print("Unknown property")
}
}
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的当前授权状态。 有三个可能的值:
available
—User has enable the Background App Refresh feature. This is the default value when app is first installed.available
用户已启用“后台应用刷新”功能。 这是首次安装应用程序时的默认值。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 codeUIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
.denied
-用户已明确禁用后台应用刷新功能。 我们可以将用户重定向到应用设置页面,以使用代码UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
切换回状态。restrict
— User is not able to toggle the background refresh status due to his account restriction, e.g. parental controlrestrict
-由于帐户限制(例如,家长控制),用户无法切换后台刷新状态
监视授权状态的更改 (Monitoring the change of authorization status)
class FooViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(backgroundRefreshStatusDidChange),
name: UIApplication.backgroundRefreshStatusDidChangeNotification, object: nil)
}
@objc
func backgroundRefreshStatusDidChange(notification: NSNotification) {
print("New status: \(UIApplication.shared.backgroundRefreshStatus)")
}
}
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)
- Background task can only be executed when user enables “Background App Refresh”. 仅当用户启用“后台应用刷新”时,才能执行后台任务。
Background task identifier must be added to “Permitted background task scheduler identifiers” field in the
info.plist
必须将后台任务标识符添加到
info.plist
“ 允许的后台任务调度程序标识符”字段中BGAppRefreshTask
can has 30s andBGProcessingTask
has more than 1 minute to complete its background task.BGAppRefreshTask
可以有30到BGProcessingTask
拥有超过1分钟内完成其后台任务。- There can be a total of 1 refresh task and 10 processing tasks scheduled at any time. 随时可以安排总共1个刷新任务和10个处理任务。
Registration of task identifier should be done before app finishes launch with options application(_:didFinishLaunchingWithOptions:)
任务标识符的注册应在应用程序通过选项application(_:didFinishLaunchingWithOptions :)启动完成之前完成
- Duplicated registration of the same task identifier can cause iOS terminate you app. 同一任务标识符的重复注册可能导致iOS终止您的应用。
- 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关注我,以获取更多信息和文章。 感谢您阅读本文。 祝你今天愉快! 😄
ios swift请求框架