Реализация фоновых задач, чтобы ваше приложение Ios было отзывчивым
Почему фоновые задачи важны для отзывчивости приложений iOS
Пользователи ожидают, что приложения iOS будут чувствовать себя мгновенно - переходы должны быть плавными, взаимодействия должны быть немедленными, а контент должен быть свежим, когда приложение открыто. Достижение этого требует разгрузочной работы, которая не должна происходить на переднем плане. Фоновые задачи позволяют вашему приложению выполнять такие операции, как синхронизация данных, предварительная выборка контента или очистка, не блокируя пользовательский интерфейс. При правильной реализации приложение остается отзывчивым на переднем плане, время автономной работы сохраняется, а системные ресурсы используются эффективно.
Ключ заключается в том, чтобы использовать правильный режим выполнения фона для каждой операции и соблюдать строгие правила iOS о выполнении фона. iOS предназначена для определения приоритетов текущего приложения пользователя и уничтожения фоновых процессов, когда требуются ограничения памяти или мощности. Поэтому понимание структуры «Фоновые задачи», введенной в iOS 13, имеет важное значение для создания современного, хорошо управляемого приложения.
Понимание выполнения фона в iOS
iOS предоставляет несколько механизмов для фоновой работы, каждый из которых подходит для различных вариантов использования. Рамка BackgroundTasks является рекомендуемым подходом для отсроченных задач, которые не должны выполняться в конкретный момент. Она работает, имея задачи системного расписания в оптимальное время, учитывая такие факторы, как сетевое подключение, уровень заряда батареи и шаблоны взаимодействия с пользователем.
Существуют и другие режимы выполнения фона для конкретных сценариев:
- Background fetch — короткая возможность (примерно 30 секунд) периодически загружать небольшие объемы контента.
- Обработка фона (FLT:0) — более длинное окно (минуты) для более тяжелых задач, таких как обслуживание базы данных или обрезка активов.
- Удаленные уведомления — пробуждение приложения для обработки полезных нагрузок с флагом .
- URLSession background transfers — загрузка или загрузка данных, даже если приложение приостановлено или прекращено.
- VoIP/аудио/локация — специализированные режимы, которые поддерживают работу приложения в течение более длительных периодов времени.
Для фоновых работ общего назначения, которые могут быть запланированы без срочности, API BGTaskScheduler является лучшим выбором. Он консолидирует планирование, снижает риск быть убитым системой и улучшает время автономной работы по сравнению с более старыми подходами, такими как FLT: 1.
Ключевые компоненты BackgroundTasks Framework
- BGProcessingTask — предназначен для задач, которые занимают заметное количество времени, например, выполнение полной синхронизации, очистка кэшированных файлов или обновление локальной базы данных.Система даёт таким задачам больший бюджет времени (минут) и запланирует их при благоприятных условиях (например, устройство на Wi-Fi и зарядка).
- BGAppRefreshTask — предназначен для коротких обновлений, обычно длящихся несколько секунд. Используйте его, когда приложению нужно обновить данные пользовательского интерфейса или извлечь небольшие объемы контента, чтобы в следующий раз, когда пользователь откроет приложение, он показывал свежую информацию. Система пытается выполнить эти задачи до того, как пользователь запустит приложение.
- BGTaskScheduler — центральный менеджер, который регистрирует идентификаторы, отправляет запросы и передает управление вашему обработчику, когда начинается задача.
Оба типа задач имеют одинаковый жизненный цикл: регистрация, расписание, обработка и перенос. Система решает, когда именно выполнить задачу; вы можете предоставить подсказку только через . Этот дизайн уважает ресурсы устройства пользователя и предотвращает беспорядок приложений в фоновом режиме.
Реализация фоновых задач - пошаговое руководство
Чтобы интегрировать фоновые задачи в ваше приложение iOS, вы должны выполнить несколько шагов: включение возможности, регистрация идентификаторов задач, планирование работы, обработка выполнения и управление истечением срока действия. Ниже мы проходим каждый этап с конкретными примерами кода.
1.Включить возможность фоновых режимов
В Xcode перейдите на вкладку Signing & Capabilities и добавьте Background Modes возможность. Проверьте, по крайней мере Background processing и/или Background fetch в зависимости от того, какие типы задач вы планируете использовать. Для BGAppRefreshTask требуется проверка Background fetch; для BGProcessingTask, Background processing.
2. Идентификаторы задач регистрации
Каждая фоновая задача должна иметь уникальную строку идентификатора, как правило, в формате обратного DNS (например, ). Вы регистрируете эти идентификаторы в начале цикла запуска приложения, например, в .
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.myapp.refresh", using: nil) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.myapp.cleanup", using: nil) { task in
self.handleDatabaseCleanup(task: task as! BGProcessingTask)
}
return true
}
Закрытие захватывает объект задачи; внутри него вы называете своего собственного обработчика. Не забудьте отбросить задачу на соответствующий конкретный тип.
3. Расписание справочных задач
Подача запросов должна происходить, когда приложение переходит в фоновый режим или возникает повторяющаяся необходимость. намекает на то, что вы хотели бы выполнить задачу, но система может отложить ее дальше.
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "com.example.myapp.refresh")
request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // at least 15 minutes from now
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh: \(error.localizedDescription)")
}
}
func scheduleDatabaseCleanup() {
let request = BGProcessingTaskRequest(identifier: "com.example.myapp.cleanup")
request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 60) // at least 1 hour
request.requiresNetworkConnectivity = true // only run when network is available
request.requiresExternalPower = true // only run when device is charging
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule cleanup: \(error.localizedDescription)")
}
}
Вызовите эти методы планирования в соответствующих местах: например, после успешной фоновой задачи (перепланировать следующий запуск) или когда пользователь приостанавливает приложение. Вы также можете позвонить им в ответ на действия пользователя, которые указывают на необходимость периодических обновлений.
4. Решение задач
Когда система решает выполнить фоновую задачу, она вызывает зарегистрированного вами обработчика. Внутри обработчика вы должны:
- Установите обработчик истечения срока действия, который отменяет текущую работу и отмечает задачу как неполную, если время истекает.
- Выполняйте фактическую работу (например, сетевой вывод, операции с базами данных).
- Позвоните после окончания работы (или после неудачи).
- Запланируйте следующее появление задачи (если задача не предназначена для одноразового выполнения).
func handleAppRefresh(task: BGAppRefreshTask) {
// Reschedule the next refresh immediately.
scheduleAppRefresh()
// Set an expiration handler that will be called if the system needs to reclaim time.
task.expirationHandler = {
// Cancel any ongoing operations, clean up resources.
// Do NOT call setTaskCompleted here; the system will mark it as expired.
}
// Perform background work (e.g., fetch new data from server).
fetchLatestData { success in
// After the work completes (or errors), inform the scheduler.
task.setTaskCompleted(success: success)
}
}
Для BGProcessingTask шаблон идентичен, но бюджет времени больше. Вы также можете выполнять более тяжелые операции, такие как уплотнение хранилища данных или изменение размера изображений.
5. Проверка исходных задач
Задачи, связанные с фоном, как известно, сложно проверить, потому что система решает, когда их запускать. Используйте следующие методы для имитации выполнения:
- Используйте отладчик Xcode: запустите приложение, затем приостановите и используйте команду (через lldb или опцию меню «Имитация фонового вывода» в симуляторе).
- Для BGProcessingTask воспользуйтесь вызовом сразу после регистрации, затем поместите приложение в фоновом режиме. Система может запустить его в течение нескольких минут.
- Используйте подход в сборке отладки: позвоните и повторно отправьте, чтобы запустить журналы планирования.
- Мониторинг выполнения задач путем установки точек останова в вашем обработчике и проверки консоли на наличие журналов.
Лучшие практики для реализации надежной фоновой задачи
Следование этим рекомендациям поможет вашему приложению оставаться отзывчивым, сохранять батарею и проходить обзор App Store.
Дизайнерские импотентные задачи
Фоновые задачи могут быть прерваны в любое время. Убедитесь, что ваша работа идемпотентна - выполнение ее несколько раз дает тот же результат, что и выполнение ее один раз. Например, используйте логику повышения производительности вместо вставки. Отслеживайте то, что было обработано с использованием временных меток или смещений, чтобы частичный прогресс был безопасным.
Уважайте экспиратора
Обработчик истечения срока действия — ваш последний шанс изящно прекратить работу. Ни при каких обстоятельствах не стоит его игнорировать. Если система вынуждает прекратить работу, то все незавершенные работы теряются. В обработчике отменяют любые текущие сетевые задачи, выпускают блокировки и сохраняют состояние контрольной точки, чтобы следующий запуск мог возобновиться.
Не переусердствуйте
Запрос фоновых задач только тогда, когда вам действительно нужны обновления контента или техническое обслуживание. Каждая отправка потребляет системные ресурсы для ведения бухгалтерского учета. Перепланировка может привести к тому, что система будет блокировать ваше приложение или отклонять задачи. Хорошая каденция для BGAppRefreshTask составляет не более 15-30 минут; BGProcessingTask может работать ежедневно или еженедельно.
Используйте ограничения мудро
BGProcessingTaskRequest предлагает и . Установите их только при необходимости. Если ваша задача может работать в автономном режиме, опустите сетевое требование — система будет иметь большую гибкость планирования и может работать раньше. Аналогично, требуя от внешнего питания задерживает задачу до тех пор, пока устройство не будет подключено, что подходит только для тяжелой работы CPU / IO.
Сохраняйте свет в работе в BGAppRefreshTask
Эти задачи имеют несколько секунд настенного времени до истечения срока действия. Принесите только то, что необходимо для обновления состояния пользовательского интерфейса. Более тяжелые операции, такие как миграция базы данных или большие загрузки, относятся к BGProcessingTask.
Тест на реальные устройства
Симулятор не полностью воспроизводит фоновое поведение при планировании задач. Тест на физическом устройстве с различными условиями зарядки, сети и зарядки. Используйте журнал энергии в Xcode Organizer, чтобы увидеть, как ваше приложение влияет на срок службы батареи.
Устранение ошибок и перепланировка
Если фоновая задача не срабатывает (например, ошибка сети), вы все равно должны перенести ее на более позднее время. Используйте экспоненциальный бэк-офф или фиксированный интервал повторного вызова. Не продолжайте звонить без перепланировки, потому что система может полностью прекратить выполнение.
Общие подводные камни и устранение неполадок
Вот частые проблемы, возникающие при выполнении фоновых задач и как их решить.
Задание никогда не выполняется
Возможные причины:
- Отсутствие возможностей - убедитесь, что включен фоновый режим.
- Несоответствие идентификатора - убедитесь, что строка, используемая в , соответствует строке в Info.plist или в .
- Задание не перезагружается – после выполнения задания (или неудачи) необходимо запланировать его повторно для будущих прогонов.
- Системные задержки - iOS может отложить выполнение фона, если устройство находится под большой нагрузкой, с низким зарядом батареи или в режиме низкого энергопотребления.
Для отладки включите logging: set logging through в сборке отладки. Затем наблюдайте за консолью для сообщений о планировании и исполнении.
Задание часто заканчивается
Если ваша задача часто достигает обработчика истечения срока действия, это означает, что вы пытаетесь сделать слишком много за разрешенное время. Профилирование с помощью инструментов (профильер времени) может выявить узкие места. Переместить тяжелые операции в BGProcessingTask или разбить работу на более мелкие куски и отслеживать прогресс.
Предупреждения или сбои памяти
Фоновые задачи выполняются в ограниченной среде. Выделите и распределите большие объекты тщательно. Используйте пулы автовыпуска для петель, которые создают много временных объектов. Если приложение терпит крах, проверьте журналы аварий для терминации с низкой памятью. Рассмотрите как место для выпуска кэшированных данных.
Передовые технологии и реальные мировые соображения
Для приложений, которые должны сбалансировать отзывчивость с фоновой работой, рассмотрите возможность объединения фоновых задач с другими функциями iOS.
Сочетание фоновых задач с Push-уведомлениями
Для временных обновлений используйте удаленные уведомления с ключом . Это разбудит приложение в фоновом режиме для короткого окна исполнения (аналогично BGAppRefreshTask). Для отсроченных обновлений прибегайте к запланированным фоновым задачам. Этот гибридный подход обеспечивает свежий контент при соблюдении срока службы батареи.
Синхронизация с CloudKit или Core Data
При выполнении фоновой синхронизации с CloudKit используйте методы фоновой синхронизации вместе с BGAppRefreshTask. Для основных данных используйте постоянное отслеживание истории, чтобы фоновый импорт не вступал в конфликт с передним планом. Всегда выполняйте записи в частном фоновом контексте.
Мониторинг выполнения задач
Используйте журнал Energy Log в Xcode (Window > Organizer > Crashes & Energy > select app > open Energy Log) чтобы увидеть, как часто выполняются фоновые задачи, их продолжительность и их влияние на батарею. Цель — сохранить время выполнения каждой задачи ниже типичного бюджета системы: ~30 секунд для BGAppRefreshTask, ~5 минут для BGProcessingTask.
Внешние ссылки
Для более глубокого изучения, обратитесь к этим авторитетным ресурсам:
- Документация Apple: BackgroundTasks
- WWDC 2019: достижения в области выполнения резервных копий приложений
- Руководство Apple: Исполнение (Legacy)
- Raywenderlich: Background Modes Tutorial
- Использование фонового исполнения для повышения энергоэффективности
Заключение
Реализация фоновых задач с помощью BGTaskScheduler и BGProcessingTask / BGAppRefreshTask позволяет создавать приложения iOS, которые чувствуют себя быстрыми и отзывчивыми, при этом выполняя необходимую фоновую работу. Следуя системному подходу, изложенному выше, — предоставляя возможности, регистрируя идентификаторы, разумно планируя, изящно обрабатывая выполнение и соблюдая системные ограничения — вы можете гарантировать, что ваше приложение балансирует свежесть с эффективностью. Тщательно тестируйте физические устройства, контролируйте энергетическое воздействие и итерируйте логику планирования. При тщательном проектировании фоновые задачи становятся неотъемлемой частью архитектуры вашего приложения, улучшая пользовательский опыт без ущерба для производительности или времени автономной работы.