On-Demand Resources — это технология Apple для отложенной загрузки контента приложения. Вместо того чтобы включать все ресурсы в установочный пакет, разработчик размещает их на серверах App Store и запрашивает по мере необходимости. По данным Apple ODR Guide, это позволяет сократить размер начальной установки и добавлять новый контент без обновления версии приложения.
Главное
On-Demand Resources (ODR) — это система управления контентом, встроенная в iOS, tvOS и macOS. Она позволяет разработчику разделить ресурсы приложения на обязательные (входят в установочный пакет) и загружаемые по требованию (хранятся в App Store и скачиваются при необходимости).
Система ODR оперирует тремя ключевыми сущностями: теги, ресурсные пакеты и запросы. Тег — это строка-идентификатор, которая объединяет группу файлов. Ресурсный пакет — набор данных, ассоциированных с тегом. Запрос — программный вызов NSBundleResourceRequest, инициирующий загрузку пакета.
Загрузка ресурса проходит несколько стадий: инициализация запроса с указанием тегов, проверка доступности в локальном хранилище, скачивание с серверов Apple при отсутствии, уведомление приложения о готовности и освобождение ресурса после использования. Система автоматически управляет кэшированием и удалением неиспользуемых ресурсов.
| Стадия | Действие системы | Время выполнения |
|---|---|---|
| Инициализация | Создание NSBundleResourceRequest с тегом | Мгновенно |
| Проверка кэша | Поиск ресурса в локальном хранилище | 0.1–0.5 с |
| Загрузка | Скачивание с CDN Apple | Зависит от размера |
| Уведомление | Вызов completion handler или делегата | Мгновенно |
| Освобождение | Пометка ресурса как удаляемого системой | По требованию iOS |
Механизм ODR основан на фоновой службе, которая управляет запросами ресурсов из облачного хранилища App Store. Когда приложение запрашивает тег, система проверяет, есть ли ресурс в локальном кэше. Если нет — начинает загрузку через фоновый URL-сессию с поддержкой возобновления при обрыве соединения.
import Foundation
class ResourceManager {
let odrRequest = NSBundleResourceRequest(tags: ["level-3"])
func loadLevel3() {
odrRequest.conditionallyBeginAccessingResources { available in
if available {
self.startLevel3()
} else {
self.odrRequest.beginAccessingResources { error in
guard error == nil else { return }
self.startLevel3()
}
}
}
}
func releaseResources() {
odrRequest.endAccessingResources()
}
}
Метод conditionallyBeginAccessingResources проверяет наличие ресурса в кэше без немедленной загрузки. Если флаг доступности положительный — приложение продолжает работу без задержки. Если ресурс отсутствует, beginAccessingResources запускает скачивание с индикацией прогресса через свойство progress.
Система iOS сама управляет приоритетами загрузки ODR-ресурсов в зависимости от текущей активности приложения. Если приложение находится на переднем плане, загрузка выполняется с высоким приоритетом. В фоновом режиме iOS может отложить загрузку или приостановить её при низком заряде батареи.
Ресурсы ODR могут включать изображения, видео, аудиофайлы, спрайты, данные уровней и любые другие файлы, не критичные для запуска приложения. Каждый ресурс привязывается к одному или нескольким тегам, которые определяют его принадлежность к функциональному блоку.
В Xcode теги настраиваются через инспектор Resource Tags на вкладке Target Membership. Разработчик указывает для каждого файла в проекте, входит ли он в основной бандл или загружается по тегу. Один файл может принадлежать нескольким тегам, что позволяет переиспользовать ресурсы между разными разделами приложения.
<!-- Пример конфигурации Resource Tags в Info.plist -->
<key>NSBundleResourceRequestTags</key>
<dict>
<key>level-3</key>
<array>
<string>levels/level3.scnassets</string>
<string>textures/level3_tex.png</string>
</array>
</dict>
Apple выделяет три категории ODR-тегов в зависимости от того, как долго ресурс должен храниться на устройстве. Initial Install Tags загружаются вместе с приложением и никогда не удаляются системой. Prefetch Tag Order определяет порядок фоновой подгрузки сразу после установки. Основные теги запрашиваются по требованию и могут быть удалены iOS при нехватке места.
Кроме категорий, каждый тег может иметь приоритет загрузки. Теги с высоким приоритетом загружаются перед низкоприоритетными, даже если они были запрошены позже. Это позволяет разработчику управлять порядком появления контента: сначала критичные ресурсы для основного экрана, затем дополнительные материалы для глубоких разделов приложения.
Настройка ODR в Xcode включает три этапа: категоризация ресурсов по тегам, конфигурация параметров загрузки в Info.plist и программная реализация запросов через NSBundleResourceRequest. Большая часть работы выполняется на стороне сборки проекта.
// Проверка статуса и мониторинг прогресса ODR
func monitorODRProgress(tag: String) {
let request = NSBundleResourceRequest(tags: [tag])
let observer = request.progress.observe(\.fractionCompleted) { progress, _ in
DispatchQueue.main.async {
let percent = Int(progress.fractionCompleted * 100)
print("ODR: \(percent)% loaded")
}
}
}
Прогресс загрузки отслеживается через свойство progress класса NSProgress с поддержкой KVO-наблюдения. Приложение может отображать индикатор загрузки пользователю во время скачивания ресурсов. После завершения загрузки ресурсы доступны в основном бандле приложения через стандартные механизмы FileManager и NSDataAsset.
Квоты на ODR зависят от версии iOS. Начиная с iOS 13, устройство может хранить до 20 ГБ загруженных по требованию ресурсов на один аккаунт. Этот объём распределяется между всеми приложениями, установленными на устройстве — если одно приложение заняло много места, другим остаётся меньше.
Мониторинг занятого места выполняется через NSBundleResourceRequest. Приложение может проверять доступное ODR-хранилище и в зависимости от этого решать, какие ресурсы загружать в первую очередь. Рекомендуется реализовать fallback-механизм: если ODR-хранилище переполнено, использовать ресурсы из основного бандла уменьшенного качества.
При превышении квоты система удаляет ресурсы с тегами On-Demand в порядке наименьшего недавнего использования, начиная с самых старых. Resource Manager в коде приложения может отслеживать текущий объём занятого ODR-хранилища через свойство NSBundleResourceRequest.Разработчику важно учитывать, что iOS может в любой момент принять решение об удалении On-Demand ресурсов — приложение должно корректно обрабатывать ситуацию, когда ранее загруженный ресурс внезапно недоступен. Рекомендуется перехватывать ошибки доступа к ресурсам и повторно запрашивать их через beginAccessingResources. Для критически важных ресурсов, без которых приложение не может функционировать, используйте Initial Install Tags, которые не удаляются системой.
On-Demand Resources дают разработчику гибкий инструмент управления размером приложения, но накладывают ряд ограничений, связанных с доступностью сети и политиками хранилища iOS.
Главное преимущество ODR — радикальное сокращение размера начальной установки. Игры с несколькими уровнями, приложения с видео-контентом или большими наборами изображений могут загружать контент порционно. Пользователь получает доступ к базовому функционалу сразу, а дополнительные ресурсы скачиваются фоном.
ODR требует постоянного подключения к интернету для загрузки ресурсов при первом обращении. Пользователь в зоне с плохим покрытием может столкнуться с задержками и ошибками загрузки. Кроме того, Apple не гарантирует, что загруженные ресурсы останутся на устройстве — при нехватке места iOS может удалить On-Demand теги без предупреждения.
Часто задаваемые вопросы
ODR позволяет добавлять и изменять ресурсы без публикации новой версии в App Store. Достаточно обновить файлы на сервере Apple через Xcode и назначить их тем же тегам. При следующем запросе приложение получит актуальную версию ресурса. Это удобно для сезонного контента, временных промо-акций и A/B тестирования новых изображений и макетов.
Система удаляет ресурсы с меткой On-Demand, когда требуется освободить место для других приложений. Ресурсы Initial Install Tags не удаляются. Порядок удаления определяется алгоритмом LRU (Least Recently Used) — первыми удаляются ресурсы, к которым дольше всего не обращались.
Начиная с iOS 13, общий лимит ODR-хранилища составляет 20 ГБ на один Apple ID пользователя. Размер одного тега не должен превышать 512 МБ для оптимальной производительности загрузки. При превышении лимита запросы завершаются ошибкой NSBundleResourceRequestLowDiskSpaceError.
Да, после загрузки ресурс сохраняется в локальном кэше и доступен в офлайн-режиме без подключения к интернету. Проблемы возникают только если iOS удалила ресурс из-за нехватки места и пользователь пытается обратиться к нему без сети.
ODR интегрирован с инфраструктурой App Store: ресурсы хостятся на CDN Apple, управляются системой кэширования и не требуют от разработчика организации собственного сервера. URLSession требует серверной инфраструктуры, контроля версий и ручного управления кэшем. ODR также автоматически обрабатывает возобновление загрузки при обрыве соединения.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также