Background threads in iOS

Alexandros Koutsonasios
2 min readJun 3, 2021

I’ve read a lot of articles regarding the background threads in iOS. Some try to use operations and some just use base swift objects. Let’s check both approaches.

Lets start with the basics. The Apple documentation is straight forward on this one.

Step One: Enable fetch and/or processing background mode in the target’s signing and capabilities tab

Background Modes: Enable the mode you want to use

Step Two: Add a permitted identifier to your Info.plist file

<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>your.refresh.identifier</string>
</array>

Step Three: Register the scheduler

static let backgroundRefreshIdentifier = "your.refresh.identifier"func setupScheduler() {
BGTaskScheduler.shared.register(forTaskWithIdentifier: AppDelegate.backgroundRefreshIdentifier, using: nil) { task in
self.handleAppRefreshTask(task: task as? BGAppRefreshTask)
}
}

And now we will take two different approaches.

Step Four: Handle the refresh

First the operation approach:

func handleAppRefresh(task: BGAppRefreshTask?) {
scheduleAppRefresh()
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 1
// myOperation is a subclass of Operation
let myOperation = MyOperation()
task?.expirationHandler = {
queue.cancelAllOperations()
}
task?.setTaskCompleted(success: !(operations.last?.isCancelled ?? false))
let operations = [operation]
queue.addOperations(operations, waitUntilFinished: false)
}

You have to create operations and the add them to a queue. Just add as many as you want in the operations array. If an operation depends on another then you have to add dependencies like:

myOperation2.addDependency(myOperation)

So looking at it the approach is getting complicated. Especially if your operations are asynchronous. You have to create a subclass of the Operation class just name it AsyncOperation and overwrite the following:

var isAsynchronous: Bool
var isExecuting: Bool
var isFinished: Bool
func start()
func main()

But this is getting complex.

So let’s take a different approach:

let refreshManager = RefreshManager()func handleAppRefreshTask(task: BGAppRefreshTask?) {
scheduleAppRefresh()
task?.expirationHandler = {
task?.setTaskCompleted(success: false)
//Kill everything you have created to play by the rules
}
refreshManager.doSomething(completionHandler: { isCompleted in
task?.setTaskCompleted(success: isCompleted)
})
}

So here you have an asynchronous call without having to implement and create asynchronous operations. You don’t care about creating a queue and adding your operations there and the result is the same at the end. The Apple framework does its magic and you can refresh your app in the background or do processing tasks.

Step Five: Schedule your task

Don’t forget to schedule your task so that your app is refreshed frequently

func scheduleAppRefresh() {
let fetchTask = BGAppRefreshTaskRequest(identifier: backgroundRefreshIdentifier)
fetchTask.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 30)
do {
try BGTaskScheduler.shared.submit(fetchTask)
} catch {
print("Unable to submit task: \(error.localizedDescription)")
}
}

That’s all someone needs to know regarding the background refresh and processing tasks in the iOS universe.

Leave any comments below :)

--

--