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 Task одновременно. Каждая задача получает свой идентификатор. Общее время выполнения суммируется — если зарегистрировано 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 button (Command + Shift + H). Используйте Debug — Simulate Background Fetch для тестирования фонового пробуждения. Для эмуляции истечения времени установите Environment Variable 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 — современную замену старому Background Task API. Оба механизма решают сходные задачи, но 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 с устройства (Volume Up + Down + Power). В 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 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

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