Background tasks allow your app to perform work when it's not actively running. Learn to schedule and execute background tasks efficiently.
Background Tasks Setup
Enable Background Modes
- 1Go to Project Settings > Signing & Capabilities
- 2Add "Background Modes" capability
- 3Enable required modes:
- Background fetch - Background processing - Remote notifications
Background Fetch
Schedule Background Fetch
swift
import BackgroundTasks
class BackgroundFetchManager {
private let backgroundTaskIdentifier = "com.yourapp.backgroundFetch"
func scheduleBackgroundFetch() {
let request = BGAppRefreshTaskRequest(identifier: backgroundTaskIdentifier)
do {
try BGTaskScheduler.shared.submit(request)
print("Background fetch scheduled")
} catch {
print("Failed to schedule background fetch: \(error)")
}
}
}Handle Background Task
swift
class AppDelegate: NSObject, UIApplicationDelegate, BGTaskSchedulerDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
BGTaskScheduler.shared.register(
forTaskWithIdentifier: "com.yourapp.backgroundFetch",
using: nil
) { task in
self.handleBackgroundFetch(task as! BGAppRefreshTask)
}
return true
}
private func handleBackgroundFetch(_ task: BGAppRefreshTask) {
// Schedule next background fetch
let nextFetch = BGAppRefreshTaskRequest(identifier: "com.yourapp.backgroundFetch")
nextFetch.earliestBeginDate = Date(timeIntervalSinceNow: 3600) // 1 hour
try? BGTaskScheduler.shared.submit(nextFetch)
// Perform background work
Task {
await self.performBackgroundWork()
task.setTaskCompleted(success: true)
}
// Expiration handler
task.expirationHandler = {
task.setTaskCompleted(success: false)
}
}
private func performBackgroundWork() async {
// Fetch data, update content, etc.
print("Performing background work")
}
}Background Processing
Schedule Background Processing
swift
class BackgroundProcessingManager {
private let processingTaskIdentifier = "com.yourapp.processing"
func scheduleBackgroundProcessing() {
let request = BGProcessingTaskRequest(identifier: processingTaskIdentifier)
request.requiresNetworkConnectivity = true
request.requiresExternalPower = false
do {
try BGTaskScheduler.shared.submit(request)
print("Background processing scheduled")
} catch {
print("Failed to schedule processing: \(error)")
}
}
}Handle Processing Task
swift
extension AppDelegate {
func registerBackgroundProcessing() {
BGTaskScheduler.shared.register(
forTaskWithIdentifier: "com.yourapp.processing",
using: nil
) { task in
self.handleBackgroundProcessing(task as! BGProcessingTask)
}
}
private func handleBackgroundProcessing(_ task: BGProcessingTask) {
// Schedule next processing
scheduleNextProcessing()
// Perform heavy processing
Task {
await performHeavyProcessing()
task.setTaskCompleted(success: true)
}
task.expirationHandler = {
task.setTaskCompleted(success: false)
}
}
private func scheduleNextProcessing() {
let request = BGProcessingTaskRequest(identifier: "com.yourapp.processing")
request.requiresNetworkConnectivity = true
try? BGTaskScheduler.shared.submit(request)
}
private func performHeavyProcessing() async {
// Process data, sync with server, etc.
}
}URLSession Background Tasks
Background Downloads
swift
class BackgroundDownloadManager: NSObject, URLSessionDelegate {
private var session: URLSession!
override init() {
super.init()
let configuration = URLSessionConfiguration.background(withIdentifier: "com.yourapp.backgroundDownload")
configuration.sessionSendsLaunchEvents = true
configuration.isDiscretionary = false
session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
}
func startBackgroundDownload(url: URL) {
let task = session.downloadTask(with: url)
task.resume()
}
}
extension BackgroundDownloadManager {
func urlSession(
_ session: URLSession,
downloadTask: URLSessionDownloadTask,
didFinishDownloadingTo location: URL
) {
// Handle downloaded file
print("Download completed to: \(location)")
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let error = error {
print("Download failed: \(error)")
}
}
}Background App Refresh
Manual Refresh Trigger
swift
class AppRefreshManager {
func triggerAppRefresh() {
let refreshTask = BGAppRefreshTaskRequest(identifier: "com.yourapp.refresh")
refreshTask.earliestBeginDate = Date(timeIntervalSinceNow: 60) // 1 minute
do {
try BGTaskScheduler.shared.submit(refreshTask)
} catch {
print("Failed to trigger refresh: \(error)")
}
}
}Background URL Session Configuration
Configure for Background Uploads
swift
class BackgroundUploadManager {
private var session: URLSession!
init() {
let config = URLSessionConfiguration.background(withIdentifier: "com.yourapp.backgroundUpload")
config.httpMaximumConnectionsPerHost = 1
config.isDiscretionary = false
session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
}
func uploadFile(fileURL: URL, to endpoint: URL) {
var request = URLRequest(url: endpoint)
request.httpMethod = "POST"
let task = session.uploadTask(with: request, fromFile: fileURL)
task.resume()
}
}
extension BackgroundUploadManager: URLSessionDelegate {
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let error = error {
print("Upload failed: \(error)")
} else {
print("Upload completed")
}
}
}Background Task Scheduler
Check Task Status
swift
extension BackgroundTasksManager {
func getTaskStatus(identifier: String) async -> BGTaskScheduler.Status? {
return await BGTaskScheduler.shared.status(forTaskWithIdentifier: identifier)
}
func cancelAllTasks() {
BGTaskScheduler.shared.cancelAllTaskRequests()
}
}Best Practices
- 1Battery: Minimize battery usage
- 2Network: Check network availability
- 3Duration: Keep tasks short
- 4Expiration: Handle task expiration
- 5Scheduling: Schedule appropriate intervals
- 6Testing: Test background modes thoroughly
- 7Fallback: Provide fallback for failures
- 8User Experience: Inform users about background activity
Background tasks enable your app to stay up-to-date!