Background Fetch — механизм iOS, который периодически пробуждает приложение в фоне для загрузки свежего контента. Система анализирует поведение пользователя и выбирает оптимальные окна для обновления. По данным Apple, 2026, приложение получает от 30 до 120 секунд на выполнение операции, после чего система приостанавливает или завершает процесс.
Главное
Background Fetch — это API iOS, позволяющий приложению периодически получать свежие данные в фоновом режиме. Впервые представлен в iOS 7 вместе с механизмом Background App Refresh. Основная цель — чтобы контент был актуален к моменту, когда пользователь откроет приложение, без необходимости ждать загрузки.
Push-уведомления инициируются сервером — он отправляет сигнал на устройство, и система решает, пробуждать приложение или нет. Background Fetch инициируется самой iOS на основе паттернов использования устройства. Push лучше подходит для срочных сообщений, Fetch — для планового обновления контента (новости, лента социальной сети).
Background Fetch — один из нескольких механизмов фонового выполнения в iOS. BGAppRefreshTask (iOS 13+) выполняет ту же задачу, но с более гибким планированием. Background Modes (audio, location) — для непрерывных операций. Silent Push — сервер-инициируемое обновление. Fetch остаётся актуальным для проектов с поддержкой iOS 12 и ниже.
iOS использует алгоритм машинного обучения для определения оптимального времени пробуждения приложения. Система анализирует, когда пользователь обычно открывает приложение, как долго его использует и как часто возвращается. На основе этих данных iOS вычисляет окна для Background Fetch.
Когда система решает пробудить приложение, она вызывает метод application(_:performFetchWithCompletionHandler:) в AppDelegate. Приложение должно загрузить минимальный объём новых данных и вызвать completion handler с одним из трёх статусов: .newData (данные загружены), .noData (нет новых данных) или .failed (ошибка). Статус влияет на частоту будущих пробуждений.
Статус .newData сообщает системе, что обновление было полезным — iOS может увеличить частоту пробуждений. .noData говорит, что данных нет — частота остаётся прежней или снижается. .failed сигнализирует о проблеме — система уменьшает частоту, чтобы не тратить батарею. Акцент должен быть на честном статусе, а не на принудительном .newData.
| Статус | Значение | Влияние |
|---|---|---|
| .newData | Данные успешно загружены | Частота может увеличиться |
| .noData | Проверка не дала новых данных | Частота остаётся прежней |
| .failed | Ошибка сети или сервера | Частота снижается |
Для включения Background Fetch необходимо выполнить два шага: активировать capability в Xcode и установить минимальный интервал в коде. Capability находится в Target — Signing & Capabilities — Background Modes — включить галочку Background Fetch. Без этого шага система не будет пробуждать приложение.
Метод UIApplication.shared.setMinimumBackgroundFetchInterval задаёт минимальное время в секундах между вызовами Fetch. Значение UIApplication.backgroundFetchIntervalMinimum (примерно 15 минут) указывает системе пробуждать приложение так часто, как это энергоэффективно. Установка интервала в application(_:didFinishLaunchingWithOptions:) — стандартная практика.
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions options: [UIApplication.LaunchOptionsKey : Any]?
)-> Bool {
UIApplication.shared.setMinimumBackgroundFetchInterval(
UIApplication.backgroundFetchIntervalMinimum
)
return true
}
При включении Background Fetch в Xcode автоматически обновляет Info.plist — добавляет ключ UIBackgroundModes со значением fetch. Это обязательный шаг: без него приложение не получит вызов performFetchWithCompletionHandler. Проверить наличие можно через P list Source или Build Settings.
Рассмотрим полную реализацию Background Fetch для приложения новостей. Реализация включает загрузку данных, кэширование и вызов completion handler. Код выполняется в AppDelegate — единственном месте, где система вызывает fetch.
func application(
_ application: UIApplication,
performFetchWithCompletionHandler handler: @escaping (UIBackgroundFetchResult) -> Void
) {
let url = URL(string: "https://api.example.com/latest")!
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {
handler(.failed)
return
}
do {
let articles = try JSONDecoder().decode([Article].self, from: data)
cacheArticles(articles)
handler(articles.isEmpty ? .noData : .newData)
} catch {
handler(.failed)
}
}.resume()
}
После загрузки данных через Background Fetch их необходимо сохранить в локальное хранилище — CoreData, UserDefaults или File Manager. При открытии приложения данные уже должны быть доступны. Используйте CoreData с фоновым контекстом для потокобезопасной записи. После сохранения обновите UI в главном потоке.
func cacheArticles(_ articles: [Article]) {
let container = NSPersistentContainer(name: "AppModel")
container.performBackgroundTask { context in
articles.forEach { article in
let entity = ArticleEntity(context: context)
entity.id = Int64(article.id)
entity.title = article.title
entity.body = article.body
}
try? context.save()
}
}
Для тестирования используйте Simulator — выберите Debug — Simulate Background Fetch в Xcode. На физическом устройстве нужно подождать, пока система решит выполнить fetch. Для ускорения можно установить минимальный интервал на 1 минуту, но система всё равно может игнорировать его при низком заряде батареи.
Background Fetch имеет ряд ограничений, которые важно учитывать при проектировании архитектуры приложения. Главное — система полностью контролирует частоту вызовов, и разработчик не может её гарантировать. Даже при установленном минимальном интервале система может не вызывать fetch часами.
Система выделяет приложению ограниченное время на выполнение задачи — обычно до 30 секунд. Если приложение не вызвало completion handler в течение этого времени, система принудительно завершает процесс и уменьшает частоту будущих пробуждений. Все сетевые запросы должны быть компактными — не более 1-2 за вызов.
iOS учитывает уровень заряда батареи при планировании Background Fetch. При заряде ниже 20% частота пробуждений снижается. При включённом режиме Low Power Mode система может полностью отключить фоновые обновления для всех приложений. Пользователь также может отключить Background App Refresh для конкретного приложения в настройках.
URLSession, запущенная из Background Fetch, работает в стандартном режиме — без поддержки background-сессий. Для больших загрузок используйте URLSession с background configuration. Система продолжит загрузку даже после завершения fetch, но прогресс не будет отслеживаться до следующего пробуждения.
Начиная с iOS 13, Apple рекомендует BGTaskScheduler как замену Background Fetch. BGTaskScheduler предоставляет более гибкое планирование, два типа задач (refresh и processing) и регистрацию задач с идентификаторами. Миграция включает несколько шагов и рекомендуется для всех новых проектов.
Первый шаг — определить идентификаторы задач в Info.plist через ключ BGTaskSchedulerPermittedIdentifiers. Второй — зарегистрировать задачи в AppDelegate через BGTaskScheduler.shared.register. Третий — заменить вызов performFetchWithCompletionHandler на обработчик, переданный в register. Четвёртый — вызвать submit для планирования задачи.
// Ранее (Background Fetch)
UIApplication.shared.setMinimumBackgroundFetchInterval(
UIApplication.backgroundFetchIntervalMinimum
)
// После миграции (BGTaskScheduler)
BGTaskScheduler.shared.register(
forTaskWithIdentifier: "com.example.refresh",
using: nil
) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
let request = BGAppRefreshTaskRequest(
identifier: "com.example.refresh"
)
request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
try? BGTaskScheduler.shared.submit(request)
BGTaskScheduler даёт больше контроля: BGProcessingTask для длительных операций (до 10 минут), условия выполнения через requiresNetworkConnectivity и requiresExternalPower, expiration handler для graceful завершения. Система также анализирует использование приложения, но Developer может задать более точные требования.
Если приложение поддерживает iOS 12 и ниже, Background Fetch остаётся единственным вариантом для периодического обновления. BGTaskScheduler доступен только с iOS 13+. В этом случае используйте обёртку: проверяйте доступность BGTaskScheduler через if #available(iOS 13, *) и вызывайте соответствующий API.
Часто задаваемые вопросы
Точная частота не документирована и зависит от поведения пользователя. Система анализирует, как часто пользователь открывает приложение, и подстраивает частоту соответствующим образом. В среднем при активном использовании fetch может вызываться 1–3 раза в час. При редком использовании — 1–2 раза в день.
Проверьте три условия: Background Fetch capability включена в Xcode, установлен minimumBackgroundFetchInterval, и пользователь не отключил Background App Refresh для приложения в настройках. Также проверьте, что устройство не в Low Power Mode и уровень заряда батареи выше 20%.
Background Fetch — старый API (iOS 7), BGAppRefreshTask — новый API (iOS 13+). BGAppRefreshTask предоставляет больше контроля: expiration handler, возможность перепланирования и проверки статуса. Background Fetch проще в реализации, но менее гибкий. Apple рекомендует использовать BGAppRefreshTask для новых проектов.
Не рекомендуется. Background Fetch ограничен по времени (до 30 секунд). Для больших загрузок используйте URLSession с background configuration — система продолжит загрузку даже после завершения fetch. Альтернатива — BGProcessingTask (iOS 13+), где доступно до 10 минут и условия для зарядки.
Да, каждое пробуждение потребляет энергию на включение процессора, инициализацию сетевого стека и загрузку данных. iOS оптимизирует частоту, чтобы минимизировать влияние. При правильной реализации — загрузка только новых данных, быстрый вызов completion handler — влияние на батарею минимально.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также