0Pricing
Swift Academy · Lesson

Background Tasks and Refresh

Schedule background work with BGTaskScheduler.

Background Tasks and Refresh is a free Swift Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why Background Tasks Exist

iOS aggressively suspends apps to save battery. To do meaningful work while backgrounded — refreshing a feed, processing a download — you schedule it through BGTaskScheduler. The system decides when to run it, balancing your needs against power and usage patterns.

import BackgroundTasks
// You request work; the system schedules it later
// at an opportune moment (charging, on Wi-Fi, etc.)

Two Task Types

There are two kinds: BGAppRefreshTask for short, frequent updates (seconds), and BGProcessingTask for longer, heavier work (minutes) like database maintenance, optionally requiring power or network.

import BackgroundTasks
// BGAppRefreshTask  -> quick content refresh
// BGProcessingTask  -> long maintenance, can require
//                      external power / network

Declaring Identifiers

Each task needs a unique identifier you list in Info.plist under BGTaskSchedulerPermittedIdentifiers. Without this declaration, registration fails. Use reverse-DNS style strings.

// Info.plist:
// BGTaskSchedulerPermittedIdentifiers = [
//   "com.example.app.refresh",
//   "com.example.app.cleanup"
// ]
let ids = "declare every identifier in Info.plist"
_ = ids

Registering a Handler

At launch, register a handler for each identifier with BGTaskScheduler.shared.register. This must happen before the app finishes launching. The handler runs whenever the system later decides to execute the task.

import BackgroundTasks
func registerTasks() {
    BGTaskScheduler.shared.register(
        forTaskWithIdentifier: "com.example.app.refresh",
        using: nil) { task in
        handleRefresh(task as! BGAppRefreshTask)
    }
}

Submitting a Request

Registering only wires up the handler. To actually ask for a run, build a BGAppRefreshTaskRequest, set the earliest begin date, and submit it. The system treats the date as a hint, not a guarantee.

import BackgroundTasks
func scheduleRefresh() {
    let request = BGAppRefreshTaskRequest(
        identifier: "com.example.app.refresh")
    request.earliestBeginDate = Date(
        timeIntervalSinceNow: 15 * 60)
    try? BGTaskScheduler.shared.submit(request)
}

Always Reschedule

A submitted request runs at most once. To keep refreshing, your handler must submit the next request before it finishes. Reschedule first, then do the work, so a crash mid-work does not stop the cycle.

import BackgroundTasks
func handleRefresh(_ task: BGAppRefreshTask) {
    scheduleRefresh() // queue the next run first
    // ... then perform this run's work
}

Signaling Completion

You must call task.setTaskCompleted(success:) when done. Forgetting it wastes your background budget and can get future tasks deprioritized. Pass whether the work succeeded so the system can adapt scheduling.

import BackgroundTasks
func handleRefresh(_ task: BGAppRefreshTask) {
    scheduleRefresh()
    Task {
        let ok = await fetchLatest()
        task.setTaskCompleted(success: ok)
    }
}
func fetchLatest() async -> Bool { true }

Respecting the Expiration Handler

The system can reclaim time early. Set task.expirationHandler to cancel ongoing work and clean up so you exit gracefully if cut short. Treat it like a deadline alarm.

import BackgroundTasks
func handle(_ task: BGAppRefreshTask) {
    let work = Task { await fetchLatest() }
    task.expirationHandler = {
        work.cancel() // stop before the OS suspends us
    }
}
func fetchLatest() async -> Bool { true }

Processing Tasks With Requirements

For heavy work, BGProcessingTaskRequest lets you set requiresNetworkConnectivity and requiresExternalPower. The system waits for those conditions, so long tasks run while the device charges overnight on Wi-Fi.

import BackgroundTasks
func scheduleCleanup() {
    let req = BGProcessingTaskRequest(
        identifier: "com.example.app.cleanup")
    req.requiresExternalPower = true
    req.requiresNetworkConnectivity = false
    try? BGTaskScheduler.shared.submit(req)
}

Testing in the Debugger

You will not wait hours for the system to schedule. Pause in the debugger and run an LLDB command to force a registered task to launch immediately, so you can verify the handler end to end.

// In LLDB while paused:
// e -l objc -- (void)[[BGTaskScheduler sharedScheduler]
//   _simulateLaunchForTaskWithIdentifier:
//   @"com.example.app.refresh"]
let test = "force-launch task via LLDB"
_ = test

A Complete Refresh Cycle

Bringing it together: register at launch, submit on background, and in the handler reschedule, guard with an expiration handler, do async work, and report completion.

import BackgroundTasks
func handleRefresh(_ task: BGAppRefreshTask) {
    scheduleRefresh()
    let work = Task { await fetchLatest() }
    task.expirationHandler = { work.cancel() }
    Task {
        let ok = await work.value
        task.setTaskCompleted(success: ok)
    }
}
func fetchLatest() async -> Bool { true }

Quick Check

Recall the lifecycle of a recurring refresh task.

Recap

You learned background scheduling:

  • BGAppRefreshTask for short refreshes, BGProcessingTask for long maintenance with power/network requirements.
  • Declare identifiers in Info.plist, register handlers at launch, and submit requests with an earliestBeginDate.
  • Reschedule the next run inside the handler, set an expirationHandler, and always call setTaskCompleted.
  • Force-launch tasks via LLDB to test.

Frequently asked questions

Is the “Background Tasks and Refresh” lesson free?

Yes — the full text of “Background Tasks and Refresh” is free to read here on the web, and the Swift Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Swift Academy course, upgrade to CoddyKit PRO.

What will I learn in “Background Tasks and Refresh”?

Schedule background work with BGTaskScheduler. You practise Swift Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Swift Academy?

No prior experience is required. Swift Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Background Tasks and Refresh” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Swift Academy lesson?

Yes. Every Swift Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Registering for Push Notifications
  2. Handling Notification Payloads
  3. Background Tasks and Refresh
  4. Notification Actions and Categories
← Back to Swift Academy