Может ли background очередь в iOS не выполниться
Что проверяют
Различаете ли вы фоновую очередь GCD и фоновый режим приложения: это разные вещи. Следом спрашивают, как гарантированно доделать загрузку, если пользователь свернул приложение.
Как отвечать
Блок, отправленный в DispatchQueue.global(qos: .background), может не выполниться или выполниться очень поздно. Причины делятся на две группы.
Жизненный цикл приложения:
- приостановка: вскоре после ухода в фон приложение замораживается, потоки стоят, блок ждёт возвращения пользователя;
- завершение процесса: система выгружает приостановленное приложение при нехватке памяти, пользователь смахивает его из переключателя. Недоделанная работа пропадает без всяких колбэков;
- низкий приоритет: QoS
.backgroundсамый низкий, в режиме энергосбережения, при перегреве и под нагрузкой такие задачи сильно откладываются.
Ошибки в коде:
- очередь остановлена: вызвали
suspend()и забылиresume(); - задача отменена:
DispatchWorkItem.cancel()до старта означает, что блок не запустится; - очередь занята: собственная последовательная очередь заблокирована долгой задачей или deadlock.
Что делать. Короткую работу при уходе в фон оборачивают в beginBackgroundTask(expirationHandler:): система даёт дополнительное время, но его длительность не гарантирована, и endBackgroundTask обязателен. Загрузки файлов отдают фоновой URLSession (URLSessionConfiguration.background(withIdentifier:)), её ведёт системный процесс, даже если приложение выгружено. Отложенную работу планируют через BGTaskScheduler, помня, что время запуска выбирает система.
Где спотыкаются
Путают QoS .background с фоновым выполнением приложения и лезут в Background Modes. Эти флаги разрешают отдельные сценарии вроде аудио, геолокации или BGTaskScheduler, а на приоритет блока в GCD не влияют.
Называют точное время жизни в фоне, например «30 секунд». Apple его не гарантирует, ориентироваться нужно на backgroundTimeRemaining и обработчик истечения времени.
Забывают, что после принудительного закрытия приложения пользователем фоновые загрузки URLSession отменяются, а задачи BGTaskScheduler перестают запускаться до следующего открытия.