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)% завантажено")
}
}
}
Прогрес завантаження відстежується через властивість 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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також