Leveraging the Power of Background Execution (Pt. 2)

How to effectively distribute and defer work from the foreground to the background.

Shot by Charles Deluvio, in Unsplash

Getting started

There are some configuration to be set in order to add tasks to the Background Scheduler. Apple has a great documentation for that with helpful resources (which you can check here). Overall, you must:

  • Tick the Background Fetch and/or Background Processing box;
  • Add this key to your Info.plist: BGTaskSchedulerPermittedIdentifiers. It is a list of Strings. You should append all your Background Task Identifiers on it;

Registering Background Tasks

Once these steps are done, you can then register the identifiers in the BGTaskScheduler using func register(forTaskWithIdentifier: String, using: DispatchQueue?, launchHandler: (BGTask) -> Void) -> Bool. Preferably, you should do it when your app is about to finish launching.

Registering a Background Task

Scheduling Background Tasks

In order to schedule background tasks, we need to submit requests to the BGTaskScheduler. These requests will hold the conditions specific to the task we want to run, such as the earliest time to begin the task.

Scheduling a BGAppRefreshTask
Scheduling a BGProcessingTask

Testing Background Tasks

We don’t control how or when the Background Scheduler launches our tasks. In fact, it is arbitrary. This is because the Scheduler will prioritise saving energy.

e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@“…”]e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateExpirationForTaskWithIdentifier:@“…”]

Outcomes

I’ve been checking this app every morning and by the evening. Accordingly to the Battery Life Software Team in Apple, the system will “learn” how you use the app and try to perform the App Refresh Tasks slightly before you actually open the app, so you can have the feeling of an always up-to-date app.

Wrapping up

We have reviewed some features and limitations of Background Tasks and behaviours of Background Execution. Below I’ve listed my main findings as well as my recommendations to you:

  • Your tasks will rely on the user’s circumstances to be launched.
  • Background Tasks are arbitrary. The system is optimised to reduce energy usage and increase device’s battery life. So we should not rely on the background to perform important work.
  • Do not schedule important business logic tasks in the background. You are not guaranteed when they will be run.
  • Do not schedule background tasks to be executed in a point far in the future.
  • If you re-subscribe a task with the same identifier, it will override the previous schedule.
  • Prevent your app to be terminated by the system while it is working on your background tasks. Set the task as completed if you finish earlier. This will keep your app in memory (suspended state) preventing it to be relaunched.
  • You have roughly 30 seconds to perform all your background tasks, not each one. Do not surpass this limit and balance it gracefully. Otherwise the system can stop launching your tasks.
  • 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.
  • Your development should be driven by the user experience. Think about your user first. Recognise your app isn’t the only one running.

Going beyond

Apple has a wide range of background execution APIs for all sorts of use cases you should definitely check out. You can find more information in Choosing Background Strategies for Your App.

Software Engineering, Concurrent Computing Enthusiast. Talk to me in 🇬🇧 & 🇧🇷 (🇮🇹 & 🇫🇷 beta).

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store