Implementing Background Tasks Using BackgroundTasks Framework
Course: iOS App Development
Topic: Implementing Background Tasks Using BackgroundTasks Framework
Course Link: iOS App Development Training
Demo Link: Register for a Free Course Demo
Website: JustAcademy
1. Introduction to Background Tasks in iOS
Background tasks allow an iOS application to perform selected operations when the application is not actively visible on the screen. These operations may include refreshing application content, synchronizing information with a server, cleaning temporary files, processing stored data, and maintaining a local database.
iOS manages background execution carefully to protect battery life, memory, and system performance. Unlike desktop applications, an iOS app cannot continue executing arbitrary code indefinitely after the user switches to another application. The operating system decides when background work can run and how much execution time it receives.
Apple provides the BackgroundTasks framework to schedule and execute suitable background operations. Developers register task handlers, submit task requests, and implement code that can safely finish or pause when the system requires it.
Why Are Background Tasks Important?
- Keep application content reasonably up to date.
- Synchronize local information with remote servers.
- Perform database maintenance and cleanup operations.
- Process data when the device has suitable resources.
- Improve the experience when users reopen the application.
- Reduce unnecessary foreground loading and waiting time.
Examples of Background Operations
| Application |
Background Operation |
| News Application |
Refresh latest news articles. |
| Shopping Application |
Synchronize product and order information. |
| Messaging Application |
Refresh selected conversation data. |
| Fitness Application |
Process and synchronize activity summaries. |
| Document Application |
Perform file synchronization and maintenance. |
| Productivity Application |
Clean temporary files and update cached information. |
2. Understanding the BackgroundTasks Framework
The BackgroundTasks framework provides APIs that allow applications to request background execution. The operating system evaluates these requests according to device conditions, application usage patterns, battery level, and available resources.
The framework does not guarantee that a task will start at an exact time. Instead, it allows an application to communicate the type of work it needs to perform and the earliest time that work should become eligible.
Important BackgroundTasks Classes
| Class |
Purpose |
| BGTaskScheduler |
Registers task handlers and submits background task requests. |
| BGTask |
Base class representing a background task managed by the system. |
| BGAppRefreshTask |
Represents a short task used to refresh application content. |
| BGProcessingTask |
Represents a longer processing or maintenance task. |
| BGAppRefreshTaskRequest |
Creates a request for an application refresh task. |
| BGProcessingTaskRequest |
Creates a request for a processing task. |
| BGContinuedProcessingTask |
Supports certain user-initiated work that starts in the foreground and can continue after the app enters the background on supported systems. |
3. Types of Background Tasks in iOS
The most commonly used scheduled task types are BGAppRefreshTask and BGProcessingTask. They are designed for different workloads and should not be treated as interchangeable.
3.1 BGAppRefreshTask
BGAppRefreshTask is intended for short operations that update application content. It is useful when an application needs to retrieve a small amount of information before the user opens it again.
Examples:
- Fetching the latest news headlines.
- Updating a weather summary.
- Refreshing a user's account information.
- Retrieving recent notifications or messages from a server.
App refresh tasks are relatively short. The system chooses when to execute them, and developers should keep the work efficient.
3.2 BGProcessingTask
BGProcessingTask is intended for operations that require more processing time than a typical content refresh. It is suitable for maintenance and processing jobs that can wait until the system has appropriate resources.
Examples:
- Cleaning old database records.
- Processing locally stored information.
- Performing data synchronization.
- Generating thumbnails for stored files.
- Performing application maintenance.
Processing tasks may be configured to require network connectivity or external power. The system can still interrupt a task, so the operation must support cancellation and recovery.
3.3 BGContinuedProcessingTask
On supported newer iOS versions, BGContinuedProcessingTask supports certain long-running operations that begin because of a user action while the app is in the foreground. If the user backgrounds the app before the operation finishes, the system can allow the work to continue under the applicable conditions.
Examples include exporting a video, processing a large collection of images, or performing a user-requested operation that needs additional time. This API is different from ordinary scheduled refresh and processing tasks because the work starts in response to a foreground action.
Comparison of Background Task Types
| Feature |
BGAppRefreshTask |
BGProcessingTask |
BGContinuedProcessingTask |
| Main Purpose |
Refresh content |
Longer maintenance and processing |
Continue user-initiated work |
| Typical Start |
Scheduled by the system |
Scheduled by the system |
Started from foreground work |
| Execution |
Short duration |
Can run for longer periods |
Can continue after the app is backgrounded |
| Common Example |
Fetch latest articles |
Clean database records |
Continue a video export |
| Scheduling Control |
System decides the execution time |
System decides based on conditions |
Uses a user-initiated task request and supported system rules |
4. Importing the BackgroundTasks Framework
To use background task APIs, import the BackgroundTasks framework into the relevant Swift file.
import UIKit
import BackgroundTasks
class AppDelegate: UIResponder, UIApplicationDelegate {
// Background task configuration
}
The framework provides the scheduler, task request classes, and task objects required to register and execute background operations.
5. Configuring Background Modes in Xcode
Before scheduling background tasks, configure the capabilities required by the application.
Configuration Steps
- Open the iOS project in Xcode.
- Select the application target from the Project Navigator.
- Open the Signing & Capabilities tab.
- Click + Capability if Background Modes is not already available.
- Add the Background Modes capability.
- Enable Background fetch for app refresh tasks.
- Enable Background processing for processing tasks.
- Save the project configuration.
Background Modes Configuration Table
| Background Mode |
Purpose |
| Background fetch |
Allows the application to request background content refresh opportunities. |
| Background processing |
Allows the application to request background processing opportunities. |
Enable only the background modes that match the application's actual requirements. Adding a capability does not guarantee that iOS will execute a task at a particular time.
6. Configuring Permitted Background Task Identifiers
Every scheduled task must use a unique identifier. The identifier must be declared in the application's permitted background task scheduler identifiers list.
For example, an application may define separate identifiers for refreshing content and cleaning a database.
Info.plist Configuration
Add the BGTaskSchedulerPermittedIdentifiers key to the application's Info.plist file. Its value must be an array containing the identifiers used by the application.
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>com.justacademy.iosapp.refresh</string>
<string>com.justacademy.iosapp.database-cleanup</string>
</array>
Understanding Task Identifiers
- Use a unique identifier for every registered task.
- Prefer reverse-domain naming conventions.
- Keep identifiers consistent between Info.plist and Swift code.
- Do not use an identifier that has not been declared as permitted.
- Avoid changing identifiers without updating the application configuration.
7. Registering a Background Task
Registration connects a task identifier with the code that should execute when the system launches the task. Register all required handlers early in the application launch sequence.
Example: Registering an App Refresh Task
import UIKit
import BackgroundTasks
class AppDelegate: UIResponder, UIApplicationDelegate {
let refreshIdentifier = "com.justacademy.iosapp.refresh"
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
BGTaskScheduler.shared.register(
forTaskWithIdentifier: refreshIdentifier,
using: nil
) { task in
guard let refreshTask = task as? BGAppRefreshTask else {
task.setTaskCompleted(success: false)
return
}
self.handleAppRefresh(task: refreshTask)
}
return true
}
func handleAppRefresh(task: BGAppRefreshTask) {
print("App refresh task started")
task.setTaskCompleted(success: true)
}
}
Explanation
- BGTaskScheduler.shared: Accesses the shared task scheduler.
- register(forTaskWithIdentifier:using:launchHandler:): Registers the identifier and its launch handler.
- refreshIdentifier: Stores the unique task identifier.
- BGAppRefreshTask: Represents the app refresh task received by the handler.
- handleAppRefresh(task:): Contains the work that should be performed.
8. Scheduling an App Refresh Task
After registering the handler, the application can submit a request to schedule a future refresh opportunity. The BGAppRefreshTaskRequest class represents this request.
Example: Scheduling a Refresh
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(
identifier: "com.justacademy.iosapp.refresh"
)
request.earliestBeginDate =
Date(timeIntervalSinceNow: 15 * 60)
do {
try BGTaskScheduler.shared.submit(request)
print("App refresh request submitted")
} catch {
print("Unable to schedule refresh: \(error)")
}
}
Explanation
- Create a BGAppRefreshTaskRequest using the registered identifier.
- Set earliestBeginDate to indicate the earliest time the task may run.
- Submit the request through BGTaskScheduler.shared.submit().
- Handle errors because the system may reject an invalid or unavailable request.
Important: earliestBeginDate is not an exact execution time. It indicates when the request becomes eligible to run. iOS decides the actual execution time.
9. Performing Data Refresh Operations
A refresh task commonly retrieves information from a server and updates local application storage. The operation should be asynchronous, efficient, and designed to handle network failures.
Example: Fetching Data Using URLSession
import Foundation
struct Article: Decodable {
let id: Int
let title: String
}
func fetchLatestArticles() async throws -> [Article] {
guard let url = URL(
string: "https://example.com/api/articles"
) else {
throw URLError(.badURL)
}
let (data, response) = try await URLSession.shared.data(
from: url
)
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
throw URLError(.badServerResponse)
}
return try JSONDecoder().decode([Article].self, from: data)
}
Explanation
- URLSession sends a network request to the configured API endpoint.
- The async function waits for the network response without blocking the main thread.
- The HTTP status code is checked before processing the response.
- JSONDecoder converts the response data into Article objects.
- The application can save the returned articles into local storage.
For production applications, use a real API endpoint, appropriate authentication, request timeouts, and robust error handling.
10. Handling Task Expiration
Background execution time is limited. If iOS needs to stop a running task, it invokes the task's expirationHandler. The application should use this handler to cancel ongoing work and release resources safely.
Example: Expiration Handler
func handleAppRefresh(task: BGAppRefreshTask) {
let operation = BlockOperation {
print("Refreshing application content...")
}
task.expirationHandler = {
operation.cancel()
print("Background task expired")
}
operation.completionBlock = {
let succeeded = !operation.isCancelled
task.setTaskCompleted(success: succeeded)
}
OperationQueue().addOperation(operation)
}
Why Is the Expiration Handler Important?
- It helps the application respond when execution time runs out.
- It allows ongoing operations to be cancelled.
- It prevents unnecessary work from continuing after expiration.
- It helps the application release resources and preserve data safely.
- It supports more reliable background task completion.
For complex operations, use a retained operation queue or task manager rather than creating temporary objects that may disappear while work is running.
11. Completing a Background Task
When the requested work finishes, the application must notify the system using setTaskCompleted(success:). This communicates whether the task completed successfully.
func finishBackgroundTask(
task: BGTask,
success: Bool
) {
task.setTaskCompleted(success: success)
}
Completion Guidelines
- Call setTaskCompleted(success:) when the operation has finished.
- Report success only when the intended work has completed successfully.
- Report failure when the operation fails or is cancelled before completion.
- Make sure every execution path reaches task completion.
- Do not report completion immediately while asynchronous work is still running.
12. Implementing BGProcessingTask
BGProcessingTask is suitable for longer background operations such as database maintenance, file processing, and data cleanup.
Example: Registering a Processing Task
func registerProcessingTask() {
BGTaskScheduler.shared.register(
forTaskWithIdentifier:
"com.justacademy.iosapp.database-cleanup",
using: nil
) { task in
guard let processingTask = task as? BGProcessingTask else {
task.setTaskCompleted(success: false)
return
}
self.handleDatabaseCleanup(task: processingTask)
}
}
Scheduling a Processing Task
func scheduleDatabaseCleanup() {
let request = BGProcessingTaskRequest(
identifier: "com.justacademy.iosapp.database-cleanup"
)
request.requiresNetworkConnectivity = false
request.requiresExternalPower = true
do {
try BGTaskScheduler.shared.submit(request)
print("Database cleanup scheduled")
} catch {
print("Scheduling failed: \(error)")
}
}
Understanding Processing Requirements
| Property |
Purpose |
| requiresNetworkConnectivity |
Indicates whether the task needs network connectivity. |
| requiresExternalPower |
Indicates whether the task should require external power. |
| earliestBeginDate |
Specifies the earliest date and time at which the request becomes eligible. |
These properties express requirements to the system. They do not force the device to run the task immediately.
13. Performing Database Maintenance in the Background
Database maintenance is a common use case for BGProcessingTask. An application may need to remove outdated records, rebuild indexes, or organize locally stored information.
Example: Database Cleanup Function
func cleanOldRecords() throws {
// Example maintenance operation.
// Replace this section with the application's
// actual database implementation.
print("Checking outdated database records")
print("Removing records that are no longer required")
print("Database cleanup completed")
}
Handling the Processing Task
func handleDatabaseCleanup(task: BGProcessingTask) {
let queue = OperationQueue()
let operation = BlockOperation()
operation.addExecutionBlock {
do {
try self.cleanOldRecords()
} catch {
print("Database cleanup error: \(error)")
}
}
task.expirationHandler = {
operation.cancel()
}
operation.completionBlock = {
task.setTaskCompleted(
success: !operation.isCancelled
)
}
queue.addOperation(operation)
}
For a real database implementation, check cancellation during long operations and use transactions where appropriate. A cancelled cleanup should leave the database in a consistent state.
14. Rescheduling Background Tasks
Background task requests are not permanent repeating schedules. If an application wants another refresh opportunity, it generally submits a new request after handling the current task.
Example: Rescheduling After Completion
func handleAppRefresh(task: BGAppRefreshTask) {
scheduleAppRefresh()
Task {
var succeeded = false
do {
let articles = try await fetchLatestArticles()
print("Received \(articles.count) articles")
succeeded = true
} catch {
print("Refresh failed: \(error)")
}
task.setTaskCompleted(success: succeeded)
}
}
This example demonstrates the rescheduling pattern. In a production implementation, coordinate cancellation and task expiration with the asynchronous operation so that the task is not marked complete while work is still running.
15. Using Background Tasks with SwiftUI
SwiftUI applications can use BackgroundTasks through an application lifecycle integration. One approach is to use an AppDelegate through UIApplicationDelegateAdaptor and register the task handlers during application launch.
Example: Connecting AppDelegate to SwiftUI
import SwiftUI
import UIKit
import BackgroundTasks
@main
struct BackgroundDemoApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self)
var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
AppDelegate Example
class AppDelegate: NSObject, UIApplicationDelegate {
let refreshID = "com.justacademy.iosapp.refresh"
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
BGTaskScheduler.shared.register(
forTaskWithIdentifier: refreshID,
using: nil
) { task in
guard let refreshTask = task as? BGAppRefreshTask else {
task.setTaskCompleted(success: false)
return
}
self.performRefresh(task: refreshTask)
}
return true
}
func performRefresh(task: BGAppRefreshTask) {
task.expirationHandler = {
print("Refresh task expired")
}
Task {
var success = false
do {
let articles = try await fetchLatestArticles()
print("Articles received: \(articles.count)")
success = true
} catch {
print("Refresh error: \(error)")
}
task.setTaskCompleted(success: success)
}
}
}
In a production SwiftUI application, the asynchronous operation should also respond to task expiration by cancelling its work. The application should use a consistent task registration and scheduling strategy.
16. Testing Background Tasks in Xcode
Background tasks are controlled by iOS, so they may not execute immediately after submission. Developers can use Xcode debugging tools to simulate task launches and expiration during development.
Testing Steps
- Run the application on a supported iOS simulator or physical device.
- Confirm that the task identifier is registered and permitted.
- Submit the background task request.
- Use Xcode's debugging options to simulate a background task launch where supported.
- Observe the launch handler and task execution logs.
- Test the expiration path and confirm that ongoing work responds to cancellation.
- Check whether the task reports successful or unsuccessful completion correctly.
Testing Checklist
- Task identifier matches the Info.plist entry.
- Background mode is enabled when required.
- Task handler is registered early during launch.
- Task request is submitted without errors.
- Expiration handling is implemented.
- Task completion is reported correctly.
- Application data remains consistent after interruption.
17. Debugging Common Background Task Errors
| Problem |
Possible Cause |
Solution |
| Task does not launch |
System has not selected the request for execution. |
Test using supported Xcode simulation tools and verify scheduling configuration. |
| Not permitted error |
Identifier is missing from BGTaskSchedulerPermittedIdentifiers. |
Add the exact identifier to Info.plist. |
| Registration fails |
Duplicate registration or incorrect identifier. |
Register each identifier once and verify its spelling. |
| Task expires |
Operation takes longer than the available execution time. |
Reduce the workload and implement cancellation. |
| Network request fails |
Network is unavailable or the server returns an error. |
Handle network errors and retry safely when appropriate. |
| Data is incomplete |
Task is interrupted before persistence finishes. |
Use atomic writes, checkpoints, and database transactions. |
| Task runs only sometimes |
Background scheduling is discretionary. |
Do not depend on an exact execution time. |
18. Best Practices for Background Task Implementation
- Keep tasks focused: Perform only the work necessary for the requested operation.
- Respect system scheduling: Do not expect a task to run at an exact time.
- Register early: Register task handlers during the application's launch sequence.
- Use unique identifiers: Keep identifiers consistent across code and Info.plist.
- Handle expiration: Cancel or safely stop ongoing operations when the system requests it.
- Report completion: Call setTaskCompleted(success:) when the task finishes.
- Save progress: Store checkpoints so interrupted work can resume safely.
- Reduce battery usage: Avoid unnecessary network calls and intensive processing.
- Use suitable APIs: Choose URLSession background transfers for large file uploads and downloads rather than treating BGAppRefreshTask as a file-transfer service.
- Test interruption: Verify that the application remains stable if a task is cancelled.
- Protect user data: Use secure storage and authenticated network requests.
- Monitor performance: Track task duration, failures, and resource usage.
19. Difference Between BackgroundTasks and beginBackgroundTask
Developers sometimes confuse scheduled background tasks with the UIKit beginBackgroundTask API. These APIs serve different purposes.
| Feature |
BackgroundTasks Framework |
beginBackgroundTask |
| Purpose |
Requests scheduled background execution. |
Requests limited extra time to finish current work when entering the background. |
| Typical Use |
Content refresh and deferred maintenance. |
Finishing a save or other critical operation. |
| Scheduling |
Managed by BGTaskScheduler. |
Started directly by the application. |
| Execution Time |
Depends on task type and system conditions. |
Limited system-granted time. |
| Completion |
BGTask.setTaskCompleted(success:) |
UIApplication.endBackgroundTask(_:) |
20. Practical Project: Background News Refresh Application
In this practical project, you will build a simple news application that requests background refresh opportunities and updates its locally stored news content.
Project Objectives
- Create a SwiftUI news application.
- Register a BGAppRefreshTask.
- Schedule a refresh request.
- Fetch news data from a remote API.
- Save the latest results locally.
- Handle expiration and network errors.
- Display updated news when the user opens the application.
Project Workflow
- The user opens the news application.
- The application registers its background refresh handler during launch.
- The application submits a refresh request.
- At an appropriate time, iOS may launch the application in the background.
- The registered handler starts the news refresh operation.
- The application retrieves the latest news from the server.
- The received information is saved to local storage.
- The application reports task completion to the system.
- The application schedules another refresh request if needed.
- When the user opens the application, the latest available local content is displayed.
Suggested Project Structure
BackgroundNewsApp/
|
|-- App/
| |-- BackgroundNewsApp.swift
| |-- AppDelegate.swift
|
|-- Models/
| |-- Article.swift
|
|-- Services/
| |-- NewsService.swift
| |-- BackgroundTaskManager.swift
|
|-- Storage/
| |-- NewsStorage.swift
|
|-- Views/
| |-- ContentView.swift
| |-- ArticleRowView.swift
|
|-- Info.plist
Expected Learning Outcome
After completing this project, you should understand how to configure background capabilities, register task identifiers, schedule refresh requests, perform asynchronous work, handle task expiration, save application data, and test background execution.
21. Common Mistakes to Avoid
- Assuming that a scheduled task will run at an exact time.
- Forgetting to add task identifiers to Info.plist.
- Registering task handlers too late during application startup.
- Using BGAppRefreshTask for heavy, long-running processing.
- Failing to implement an expiration handler.
- Forgetting to call setTaskCompleted(success:).
- Leaving long-running operations without cancellation support.
- Assuming background tasks continue indefinitely after the application is terminated.
- Performing large file transfers using an unsuitable background execution approach.
- Failing to persist important progress before a task is interrupted.
22. Interview Questions and Answers
Q1. What is the BackgroundTasks framework in iOS?
Answer: BackgroundTasks is an Apple framework that allows applications to request system-managed background execution for tasks such as refreshing content and performing maintenance operations.
Q2. What is BGTaskScheduler?
Answer: BGTaskScheduler is the central class used to register background task handlers and submit task requests.
Q3. What is BGAppRefreshTask?
Answer: BGAppRefreshTask represents a short background operation used to refresh application content, such as retrieving updated news or account information.
Q4. What is BGProcessingTask?
Answer: BGProcessingTask is designed for longer background operations, including database maintenance, data processing, and application cleanup.
Q5. What is the purpose of BGTaskSchedulerPermittedIdentifiers?
Answer: It is an Info.plist key containing the list of background task identifiers that the application is permitted to register and schedule.
Q6. What does earliestBeginDate do?
Answer: It specifies the earliest date and time when a background task request becomes eligible to run. It does not guarantee execution at that exact time.
Q7. What is an expiration handler?
Answer: An expiration handler is a closure called by the system when a running background task is about to expire. It allows the application to cancel ongoing work and clean up resources.
Q8. Why should a background task call setTaskCompleted(success:)?
Answer: It informs the operating system that the task has finished and reports whether the operation succeeded.
Q9. Can an iOS background task run indefinitely?
Answer: No. Background execution is controlled by the operating system and depends on task type, device conditions, and available resources.
Q10. What is the difference between BGAppRefreshTask and BGProcessingTask?
Answer: BGAppRefreshTask is designed for short content updates, while BGProcessingTask is intended for longer maintenance and processing operations.
Q11. Why might a background task not execute immediately?
Answer: iOS schedules background work according to system conditions, battery usage, device activity, and application usage patterns. A submitted request is not an exact-time appointment.
Q12. What is BGContinuedProcessingTask?
Answer: It is an API available on supported newer iOS versions for certain user-initiated foreground operations that can continue after the application moves into the background.
23. Practical Exercises
- Create a SwiftUI application that registers a BGAppRefreshTask.
- Add a permitted task identifier to Info.plist.
- Schedule an app refresh request using BGAppRefreshTaskRequest.
- Create a function that fetches data from a sample REST API.
- Save fetched information into local application storage.
- Register a BGProcessingTask for database maintenance.
- Configure a processing task to require external power.
- Implement an expiration handler that cancels an operation.
- Test background task execution using Xcode debugging tools.
- Build a background news refresh application and document its execution flow.
24. Quick Revision Notes
| Concept |
Quick Explanation |
| BackgroundTasks |
Framework for system-managed background execution. |
| BGTaskScheduler |
Registers and schedules background tasks. |
| BGAppRefreshTask |
Used for short content refresh operations. |
| BGProcessingTask |
Used for longer maintenance and processing operations. |
| BGTaskRequest |
Represents a request for background execution. |
| earliestBeginDate |
Defines the earliest eligible execution time. |
| Expiration Handler |
Handles cancellation when task time expires. |
| setTaskCompleted() |
Reports task completion to the system. |
| Info.plist |
Stores permitted background task identifiers. |
| Background Modes |
Enables the background capabilities required by the app. |
| BGContinuedProcessingTask |
Supports eligible user-initiated work that continues in the background on supported systems. |
25. Conclusion
Implementing background tasks using the BackgroundTasks framework is an important part of building reliable iOS applications. It allows developers to request opportunities for content refresh, data synchronization, and maintenance while respecting the operating system's execution limits.
By understanding BGTaskScheduler, BGAppRefreshTask, BGProcessingTask, task registration, scheduling, expiration handling, and completion reporting, developers can build applications that keep information updated without wasting system resources.
The most important principle is to design background operations that are efficient, cancellable, and safe to resume. Since iOS controls when scheduled tasks execute, applications should never depend on background execution happening at an exact time.
Additional Learning Resources