iOS does not have a fixed-interval scheduler. registerPeriodicTask is treated as a BGAppRefreshTaskRequest, where the frequency parameter is ignored. The system decides when and if the task runs based on usage patterns.
To achieve more predictable intervals, use Task Chaining: schedule the next run from inside the current task's callback. This ensures the next link is submitted to the BGTaskScheduler and survives app relaunches.
Chaining Characteristics:
- Intervals are floors, not cadences: Intervals will drift and can stretch to hours.
- Requires successful execution: The chain only advances when a link runs and re-submits. If the app is force-quit, the chain stalls.
- App updates: Requests may not survive updates. It is recommended to re-seed the chain from your app's startup path (e.g.,
main). - Failure handling: Returning
false from a task tells iOS the task failed, which may cause the system to defer future runs. Implement your own backoff by adjusting the initialDelay in the next scheduled task.
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((taskName, inputData) async {
// ... do the work ...
// Schedule the next run to maintain the chain
Workmanager().registerPeriodicTask(
"com.example.sync",
"sync",
initialDelay: Duration(hours: 1),
);
return true;
});
}