Background Task: ключові поняття, реєстрація завдань і виконання у фоновому режимі

Автор: IT Sectr Опубліковано: 2026-03-27 Час читання: 10 хв

Background Task — це механізм iOS, який дозволяє застосунку завершити розпочату операцію після переходу у фоновий режим. Система виділяє обмежений час (до 30 секунд) на виконання завдання, після чого застосунок примусово призупиняється. За даними Apple, 2026, використання expiration handler є обов'язковою вимогою для коректного завершення фонового завдання.

Головне

  • Background Task — механізм iOS для завершення операцій після переходу застосунку в фон.
  • beginBackgroundTask — ключовий метод UIApplication для реєстрації фонового завдання.
  • Expiration handler — блок коду, що викликається системою при вичерпанні виділеного часу.
  • Обмеження 30 секунд — стандартний час виконання, продовження через Background Modes.
  • UIApplication.shared.endBackgroundTask — обов'язковий виклик для коректного завершення завдання.

Що таке Background Task в iOS?

Background Task — це програмний механізм iOS, що дозволяє застосунку продовжити час виконання після переходу у фоновий режим. Коли користувач згортає застосунок, система викликає UIApplicationDelegate.applicationDidEnterBackground. Якщо в цей момент виконується критична операція (збереження даних, надсилання запиту), застосунок може запросити додатковий час через beginBackgroundTask.

Навіщо потрібні Background Tasks

Без використання Background Task застосунок примусово призупиняється через 3–5 секунд після переходу в фон. Усі незавершені операції перериваються: дані не зберігаються, мережеві запити обриваються, стани втрачаються. Background Task дає застосунку до 30 секунд для коректного завершення цих операцій.

  • Збереження стану — запис даних у CoreData, UserDefaults або файлову систему.
  • Завершення мережевих запитів — дочекатися відповіді від сервера та обробити результат.
  • Надсилання аналітики — передача подій на сервер аналітики перед призупиненням.
  • Очищення ресурсів — закриття файлових дескрипторів, звільнення пам'яті.
  • Кешування — запис проміжних результатів для відновлення при наступному запуску.

Історія та еволюція

beginBackgroundTask з'явився в iOS 4.0 — першому релізі, що підтримує багатозадачність. До iOS 4 застосунок повністю завершувався при натисканні кнопки Home. З iOS 7 з'явилися Background Fetch та URLSession background configuration. Починаючи з iOS 13, Apple рекомендує BGTaskScheduler для нових проєктів, але beginBackgroundTask залишається актуальним для короткострокових операцій.

Як працює beginBackgroundTask: життєвий цикл

beginBackgroundTask — метод UIApplication, який реєструє завдання та повертає унікальний ідентифікатор UIBackgroundTaskIdentifier. Система збільшує таймер фонового виконання. Після вичерпання часу викликається expiration handler, після чого застосунок має викликати endBackgroundTask(identifier:) для коректного завершення.

Покроковий процес виконання

Крок 1 — застосунок отримує сповіщення didEnterBackground. Крок 2 — викликається beginBackgroundTask(expirationHandler:). Крок 3 — виконується критична операція (збереження, мережевий запит). Крок 4 — після завершення викликається endBackgroundTask(identifier:). Якщо операція не завершилася за 30 секунд — система викликає expiration handler, і застосунок має негайно завершити завдання.

swift
var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid

func startBackgroundTask() {
    backgroundTaskID = UIApplication.shared.beginBackgroundTask {
        // Expiration handler
        UIApplication.shared.endBackgroundTask(backgroundTaskID)
        backgroundTaskID = .invalid
    }
}

func finishBackgroundTask() {
    UIApplication.shared.endBackgroundTask(backgroundTaskID)
    backgroundTaskID = .invalid
}

UIApplication.shared.backgroundTimeRemaining

Властивість backgroundTimeRemaining повертає кількість секунд, що залишилися до примусового завершення фонового завдання. Значення зменшується в реальному часі. Якщо застосунок не у фоні — повертає DBL_MAX. Використовуйте цю властивість для адаптації поведінки: при залишку менше 5 секунд переривайте тривалі операції та зберігайте прогрес.

Множинні завдання

Застосунок може зареєструвати кілька Background Tasks одночасно. Кожне завдання отримує свій ідентифікатор. Загальний час виконання підсумовується — якщо зареєстровано 3 завдання, застосунок може отримати до 90 секунд. Однак система може завершити застосунок раніше, якщо вичерпано ресурси або перевищено ліміт батареї.

Expiration handler: обов'язкова обробка завершення

Expiration handler — це блок коду, який система викликає при вичерпанні виділеного часу на фонове завдання. Наявність expiration handler є обов'язковою вимогою Apple. Без нього застосунок може бути примусово завершений системою, а дані — втрачені.

Що має бути в expiration handler

Expiration handler має виконати мінімальні дії для збереження стану застосунку: зберегти поточні дані у постійне сховище, викликати endBackgroundTask з відповідним ідентифікатором та встановити ідентифікатор у .invalid. Всередині expiration handler заборонено запускати нові тривалі операції — час виконання обмежений 1–2 секундами.

swift
func handleExpiration() {
    // Зберігаємо прогрес виконання
    saveProgressToUserDefaults()

    // Скасовуємо активні мережеві запити
    currentTask?.cancel()

    // Завершуємо Background Task
    UIApplication.shared.endBackgroundTask(backgroundTaskID)
    backgroundTaskID = .invalid
}

// Реєстрація з expiration handler
backgroundTaskID = UIApplication.shared.beginBackgroundTask(
    withName: "SaveDocument",
    expirationHandler: handleExpiration
)

Помилки при роботі з expiration handler

Найпоширеніша помилка — не викликати endBackgroundTask всередині expiration handler. У цьому випадку система продовжує вважати завдання активним, застосунок не переходить у стан Suspended, і батарея розряджається. Друга помилка — запуск тривалих операцій всередині expiration handler. Система може завершити застосунок до їх завершення, і дані будуть втрачені.

Перевірка часу, що залишився

В expiration handler час виконання критично малий — зазвичай менше 1 секунди. Тому всередині handler не можна виконувати: складні обчислення, мережеві запити, запис великих обсягів даних у CoreData. Лише атомарні операції: запис одного ключа в UserDefaults, встановлення прапорця стану, виклик endBackgroundTask.

Приклади коду Background Task на Swift

Розглянемо повну реалізацію Background Task для збереження документа при переході застосунку в фон. Приклад включає реєстрацію завдання, виконання операції з перевіркою часу, що залишився, та коректне завершення через endBackgroundTask.

Збереження документа з прогресом

При переході в фон застосунок ініціює збереження великого документа. Background Task дає до 30 секунд на операцію. Якщо час вичерпується — expiration handler зберігає проміжні результати. Після завершення збереження викликається endBackgroundTask для звільнення ресурсів.

swift
class DocumentManager {
    private var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid

    func saveDocumentInBackground(document: Document) {
        backgroundTaskID = UIApplication.shared.beginBackgroundTask {
            self.saveProgress(document)
            self.endBackgroundTask()
        }

        DispatchQueue.global().async {
            document.save()
            self.endBackgroundTask()
        }
    }

    private func endBackgroundTask() {
        UIApplication.shared.endBackgroundTask(backgroundTaskID)
        backgroundTaskID = .invalid
    }
}

Надсилання даних на сервер

Мережеві запити у фоні потребують особливої уваги — expiration handler може перервати запит до отримання відповіді. Використовуйте URLSession з dataTask та перевіряйте backgroundTimeRemaining перед надсиланням. Якщо залишилося менше 5 секунд — відкладіть надсилання до наступного пробудження застосунку.

swift
func sendCriticalData(data: Data) {
    backgroundTaskID = UIApplication.shared.beginBackgroundTask {
        // Зберігаємо дані для повторного надсилання
        saveForRetry(data)
        self.endBackgroundTask()
    }

    let task = URLSession.shared.dataTask(with: request) { _, _, error in
        if error != nil {
            saveForRetry(data)
        }
        self.endBackgroundTask()
    }
    task.resume()
}

Моніторинг часу, що залишився

Для тривалих операцій відстежуйте UIApplication.shared.backgroundTimeRemaining. Якщо значення падає нижче порогу (10 секунд), перервіть поточну операцію та запустіть збереження проміжних результатів. Це дозволяє коректно завершити роботу до примусового виклику expiration handler.

Найкращі практики використання Background Task

Background Task — потужний механізм, але його неправильне використання призводить до проблем із батареєю та продуктивністю. Дотримання рекомендацій Apple та перевірених практик спільноти допоможе уникнути типових помилок і забезпечити стабільну роботу застосунку.

Мінімізація часу виконання

Завершуйте Background Task якомога швидше. Кожна секунда фонового виконання витрачає заряд батареї. Оптимальний час — менше 5 секунд. Якщо операція займає більше — розгляньте використання BGTaskScheduler або Background Modes. Не продовжуйте завдання штучно через виклики beginBackgroundTask без реальної необхідності.

Правильне використання ідентифікаторів

Зберігайте UIBackgroundTaskIdentifier як властивість класу або структури. Ніколи не передавайте його як глобальну змінну — це призводить до конфліктів при множинних завданнях. Встановлюйте ідентифікатор у .invalid після виклику endBackgroundTask для запобігання подвійному завершенню.

Тестування Background Task

У Xcode Simulator перемкніть застосунок у фон через кнопку Home (Command + Shift + H). Використовуйте Debug — Simulate Background Fetch для тестування фонового пробудження. Для емуляції вичерпання часу встановіть змінну середовища BACKGROUND_TASK_SIMULATE_EXPIRATION = YES — expiration handler буде викликано через 5 секунд.

swift
// Перевірка часу, що залишився, перед початком операції
let remaining = UIApplication.shared.backgroundTimeRemaining
guard remaining > 10.0 else {
    // Недостатньо часу — відкласти завдання
    scheduleForNextLaunch()
    return
}

// Виконання операції з контролем часу
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
    saveProgress()
    self.endBackgroundTask()
}

Уникайте retain cycles

Expiration handler захоплює self — це може створити retain cycle, якщо backgroundTaskID зберігається як властивість того ж об'єкта. Використовуйте [weak self] у замиканні або зберігайте ідентифікатор окремо. Retain cycle призведе до витоку пам'яті — об'єкт не буде звільнено до завершення застосунку.

Background Task vs BGTaskScheduler: порівняння підходів

З виходом iOS 13 Apple представила BGTaskScheduler — сучасну заміну старого API Background Task. Обидва механізми вирішують схожі завдання, але BGTaskScheduler надає більше контролю та гнучкості. Розуміння відмінностей допоможе вибрати правильний інструмент для конкретного сценарію.

ХарактеристикаBackground TaskBGTaskScheduler
Версія iOS4.0+13.0+
Макс. час30 секунд30 с / 10 хв (processing)
ІніціаціяdidEnterBackgroundПланування + система
Гарантія виконанняТільки при переході в фонУ будь-який зручний для системи час
Expiration handlerТак, обов'язковийТак, через task.expirationHandler
ІнтернетПотрібен при запускуДоступний через requiresNetworkConnectivity
ЗаряджанняНе потрібнеОпціонально для processing

Коли використовувати Background Task

beginBackgroundTask підходить для короткострокових операцій, які потрібно виконати негайно при переході в фон: збереження стану, завершення мережевого запиту, кешування даних. API простий і не вимагає налаштування Info.plist або реєстрації ідентифікаторів. Ідеальний для операцій, що займають менше 10 секунд.

Коли використовувати BGTaskScheduler

BGTaskScheduler підходить для завдань, які можуть бути виконані в будь-який зручний час: періодична синхронізація, очищення кешу, оновлення віджетів. Система сама обирає оптимальний час з урахуванням поведінки користувача та стану батареї. Для тривалих операцій (до 10 хвилин) використовуйте BGProcessingTask.

Спільне використання

Обидва API можна використовувати в одному застосунку. Background Task — для негайних операцій при переході в фон (збереження чернетки). BGTaskScheduler — для планових оновлень (синхронізація кожні 6 годин). Розділення відповідальності дозволяє гарантувати коректне збереження даних та енергоефективне фонове обслуговування.

Часті запитання

Чи можна викликати beginBackgroundTask не в didEnterBackground?

Так, beginBackgroundTask можна викликати в будь-який момент роботи застосунку. Однак системне виділення часу почнеться тільки після переходу в фон. Якщо застосунок на передньому плані, виклик beginBackgroundTask не має ефекту — backgroundTimeRemaining повертає DBL_MAX, а завдання буде активовано при переході в фон.

Що станеться, якщо не викликати endBackgroundTask?

Якщо не викликати endBackgroundTask, система продовжить вважати застосунок активним у фоні. Через 30 секунд буде викликано expiration handler, але якщо і в ньому немає endBackgroundTask — застосунок залишиться в пам'яті, витрачаючи батарею. В iOS 13+ система примусово завершує такий застосунок через 3 хвилини.

Як збільшити час Background Task понад 30 секунд?

Стандартний час — 30 секунд. Збільшити його можна тільки через Background Modes: Audio (відтворення), Location (геолокація), Bluetooth (BLE). Або через BGProcessingTask (iOS 13+) — до 10 хвилин за умови заряджання та Wi-Fi. beginBackgroundTask сам по собі не надає способу збільшити ліміт.

Чи працює Background Task на iPad?

Так, iPadOS повністю підтримує beginBackgroundTask з тими ж обмеженнями, що й iOS. На iPad з Stage Manager застосунок може залишатися в пам'яті довше — система рідше призупиняє застосунки через більший обсяг RAM. Але ліміт 30 секунд на фонове завдання зберігається.

Як налагодити Background Task на реальному пристрої?

Підключіть пристрій до Xcode, запустіть застосунок, згорніть його — у консолі з'являться логи системи. Використовуйте sysdiagnose для збору детальних логів: примусово викличте sysdiagnose з пристрою (Гучність + + Гучність − + Живлення). У Xcode Debug Navigator відстежуйте активність фонових завдань.

Підсумки

  • Background Task — механізм iOS для завершення операцій після переходу в фон, доступний з iOS 4.0.
  • beginBackgroundTask — метод UIApplication, що реєструє завдання та повертає ідентифікатор для його завершення.
  • Expiration handler — обов'язковий блок коду, що викликається системою при вичерпанні 30-секундного ліміту.
  • endBackgroundTask — обов'язковий виклик для коректного завершення завдання; без нього застосунок залишається в пам'яті.
  • BGTaskScheduler — сучасна альтернатива (iOS 13+) з плануванням, двома типами завдань та умовами виконання.
  • backgroundTimeRemaining — властивість для перевірки часу, що залишився, та адаптації поведінки завдання.
  • Використовуйте Background Task для негайних короткострокових операцій та BGTaskScheduler для планових фонових оновлень у нових проєктах.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також