The Constraints

iOS is aggressive about battery. You cannot run forever. You get short windows of time decided by the OS heuristics.

BGAppRefreshTask

Short (<30s) tasks to update content. Used for ensuring the app is fresh when the user opens it.

BGProcessingTask

Longer minutes-long tasks (e.g., database training, photo upload). Takes place only when device is charging and idle.

Silent Push Notifications

Send a push with "content-available: 1". It wakes the app in background to fetch data. Don't abuse it or Apple throttles you.

Scheduling Logic

Use BGTaskScheduler.shared.submit. Note: "earliestBeginDate" is a suggestion, not a guarantee. The system decides execution.

Debugging Background Tasks

Hard to test naturally. Use the debugger command e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier: @"YOUR_ID"].

Best Practices

Always call task.setTaskCompleted. If you don't, iOS assumes you hung and kills your app/penalizes future time.