Статьи

Введение в ресурсы по запросу на iOS и tvOS

Наряду с iOS 9 и watchOS 2 Apple представила ресурсы по требованию, новый API для доставки контента в ваши приложения, одновременно уменьшая объем пространства, которое приложение занимает на устройстве пользователя. С помощью ресурсов по запросу вы можете пометить определенные ресурсы вашего приложения, разместить их на серверах Apple, что позволит вашим пользователям загружать их при необходимости. В этом уроке я собираюсь показать вам основы ресурсов по требованию, создав базовое приложение для просмотра изображений.

Это руководство требует, чтобы вы работали с Xcode 7+ и были знакомы с разработкой для iOS. Вам также нужно будет скачать стартовый проект GitHub .

Ресурсы по требованию были введены в iOS 9 и watchOS 2 с главной целью уменьшения количества места, занимаемого отдельными приложениями на устройстве. Другое важное преимущество ресурсов по требованию состоит в том, что пользователи могут быстрее загружать и открывать ваше приложение.

Ресурсы по требованию работают, назначая уникальные теги ресурсам в XCode, чтобы создать так называемый пакет ресурсов . Эти пакеты могут включать в себя что угодно из каталогов ресурсов (изображения, текстуры SpriteKit, данные и т. Д.) Или даже просто другие файлы, такие как шейдеры OpenGL и Metal, а также сцены SpriteKit и SceneKit и системы частиц.

Когда вы отправляете свое приложение в App Store, эти ресурсы также загружаются и размещаются там, чтобы их можно было загрузить в любое время. Чтобы загрузить пакеты ресурсов во время выполнения в приложении, вы просто используете тег для каждого пакета, который вы назначили в XCode.

Двумя основными аспектами приложения, которое использует ресурсы по требованию, является пакет приложений , который полон исполняемого кода для вашего приложения и основных ресурсов, таких как значки пользовательского интерфейса и пакеты ресурсов .

Для этих пакетов активов есть три главных категории, которые вы можете организовать в XCode:

  • Начальная установка. Это содержимое, которое требуется для запуска вашего приложения в первый раз, но которое можно удалить позже. Это может включать в себя первые несколько уровней игры, которые больше не нужны, когда игрок продвигается достаточно далеко в игру.
  • Предварительно выбранные. В эту категорию входит содержимое, которое вы хотите загрузить сразу после завершения установки приложения. Этот тип контента рекомендуется для ресурсов, которые не требуются для работы вашего приложения после его установки, но которые необходимы для лучшего взаимодействия с пользователем. Хорошим примером являются учебники для игры.
  • По требованию: эта категория предназначена для контента, который вам нужен позже, и ваше приложение может работать без него. При работе с ресурсами по требованию это наиболее распространенный тип категории, который вы будете использовать.

Приложения, созданные с поддержкой ресурсов по требованию, должны также придерживаться следующих ограничений в отношении размера файла:

  • 2 ГБ для комплекта приложений для iOS
  • 2 ГБ для тегов установки i nitial
  • 2 ГБ для предварительно выбранных тегов
  • 2 ГБ для используемых ресурсов. Это важно только тогда, когда ваше приложение работает и использует ресурсы по требованию.
  • 512 МБ для каждого отдельного пакета активов. Ни один тег не может содержать больше этого количества данных. Если вы превысите этот лимит, Xcode выдаст вам предупреждение и позволит вам все еще тестировать и разрабатывать свое приложение. Однако любая попытка отправки в App Store не удастся.
  • 20 ГБ для всех ресурсов, размещенных в Apple. Это общее количество ресурсов, которое ваше приложение может загрузить за один раз. Хотя в каждый момент времени можно использовать только 2 ГБ, если на устройстве пользователя достаточно памяти, до 20 ГБ ваших ресурсов можно загрузить и сделать доступными для вашего приложения в любое время.

Обратите внимание, что общий объем в 20 ГБ не учитывает срезы приложений, в то время как все остальные итоги -. Что такое нарезка приложений? Разрезание приложений — это еще одна функция, которая была введена в iOS 9 для уменьшения размера приложений. Это делается только путем просмотра ресурсов, специфичных для устройства, на котором устанавливается приложение. Например, если каталоги ресурсов используются правильно, приложение, установленное на iPhone 6 Plus или 6s Plus, должно загружать только изображения в масштабе 3x и не беспокоиться о масштабах 1x и 2x. Для ресурсов по требованию 20 ГБ общих ресурсов, которые вы можете загрузить на серверы App Store, — это общая сумма для всех типов устройств. Все остальные ограничения относятся к каждому конкретному устройству, на котором устанавливается ваше приложение.

Что касается удаления данных (очистки), пакеты ресурсов, загруженные вашим приложением, будут удалены только тогда, когда на устройстве, на котором установлено ваше приложение, заканчивается свободное место. Когда это происходит, система ресурсов по запросу просматривает все приложения на устройстве и, выбрав одно, проверяет свойство сохранения каждого пакета ресурсов, а также время его последнего использования. Важно отметить, что пакеты ресурсов для вашего приложения никогда не будут очищаться во время его работы.

Откройте стартовый проект в Xcode и запустите приложение в iOS Simulator. На данный момент это базовое приложение содержит коллекцию изображений, каждое из которых имеет комбинацию одного из трех цветов (красный, зеленый или синий) и одной из четырех форм (круг, квадрат, звезда или шестиугольник). Когда приложение запущено, перейдите в « Цвета»> «Красный», и на экране отобразится изображение красного круга.

Меню приложения
Цветное меню
Красный круг

В этом приложении мы собираемся настроить в общей сложности семь пакетов ресурсов, один для каждого цвета и один для каждой фигуры. Еще одна замечательная особенность ресурсов по требованию состоит в том, что одному ресурсу может быть назначено более одного тега. Красный круг, например, может быть частью как пакета ресурсов Red, так и пакета ресурсов Circle .

API ресурсов по требованию также достаточно умен, чтобы не загружать и не копировать один и тот же ресурс дважды. Другими словами, если приложение уже загрузило пакет ресурсов Red и затем хотело загрузить пакет ресурсов Circle , изображение красного круга больше не будет загружаться.

В Xcode откройте Assets.xcassets . Вы должны увидеть все двенадцать изображений, как показано ниже.

Каталог активов

Затем выберите набор изображений Blue Square и откройте инспектор атрибутов справа.

Атрибут Инспектор

Вы увидите, что Инспектор атрибутов содержит новый раздел « Теги ресурсов по требованию », в котором вы назначаете теги для каждого ресурса. Для набора синего квадрата введите « Синий и квадрат» в поле « Теги ресурса по требованию» . Это означает, что для набора изображений теперь назначены два тега.

Голубые квадратные метки

Обратите внимание, что стартовый проект уже содержит теги ресурсов для девяти из двенадцати наборов изображений. Это объясняет, почему Xcode предоставляет вам варианты автозаполнения, когда вы вводите эти теги.

После того, как вы завершили назначение тегов для набора изображений Blue Square , добавьте правильные теги к обоим Набор изображений зеленого шестиугольника и красного круга показан ниже.

Бирки зеленого шестиугольника
Красный круг Теги

Если теги ресурсов по требованию настроены правильно, откройте их в Навигаторе проектов слева. Откройте вкладку « Теги ресурса » вверху и выберите фильтр « Предварительно выбранные» вверху.

Обзор тегов

Теперь вы можете увидеть, насколько велик каждый пакет ресурсов и какие ресурсы в каждом из них. Фильтр Все показывает вам каждый из ресурсов по требованию. Фильтр Prefetched показывает ресурсы по запросу для каждой категории и позволяет вам перемещать ресурсы из одной категории в другую:

  • Начальная установка тегов
  • Предварительно выбранный порядок тегов
  • Скачать только по требованию

Эти разделы отражают три категории пакетов ресурсов, которые я описал ранее. Важно отметить, что пакеты ресурсов, помещенные вами в раздел « Порядок предварительно выбранных тегов », начнут загружаться в том порядке, в котором они отображаются.

С тегами, назначенными каждому набору изображений, пришло время начать доступ к ресурсам в проекте.

Доступ к пакетам ресурсов, размещенным на серверах App Store, обрабатывается новым классом NSBundleResourceRequest . Экземпляр этого класса создается с набором тегов, которые вы хотите использовать. Он сообщает системе об использовании вами соответствующих пакетов активов. NSBundleResourceRequest этих объектов NSBundleResourceRequest — лучший и самый простой способ сообщить операционной системе, когда вы больше не используете конкретный пакет ресурсов. Это важно, чтобы вы не превышали ограничение 2 ГБ для используемых ресурсов.

В вашем проекте откройте DetailViewController.swift и добавьте следующее свойство в класс DetailViewController .

1
var request: NSBundleResourceRequest!

Затем замените ваш viewDidAppear(_:) следующим:

01
02
03
04
05
06
07
08
09
10
11
12
13
override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
     
    request = NSBundleResourceRequest(tags: [tagToLoad])
    request.beginAccessingResourcesWithCompletionHandler { (error: NSError?) -> Void in
        // Called on background thread
        if error == nil {
            NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
                self.displayImages()
            })
        }
    }
}

С помощью этого кода вы сначала инициализируете свойство request набором, включающим один тег. Набор тегов, которые вы предоставляете этому инициализатору, содержит строковые значения. В этом случае мы используем свойство tagToLoad , которое устанавливается предыдущими контроллерами представления в приложении.

Затем мы начинаем загрузку пакетов ресурсов для указанных тегов, вызывая beginAccessingResourcesWithCompletionHandler(_:) . Этот метод получит доступ ко всем ресурсам с указанными тегами и автоматически начнет загрузку при необходимости. После такого доступа к ресурсам весь ваш другой код для загрузки этих ресурсов в ваше приложение остается прежним.

Обратите внимание, что если вы хотите получить доступ только к уже загруженным ресурсам без загрузки контента, вы можете использовать метод conditionallyBeginAccessingResourcesWithCompletionHandler(_:) .

Как показано в приведенном выше коде, следует помнить одну важную вещь об этом обработчике завершения: он вызывается в фоновом потоке. Это означает, что любые обновления пользовательского интерфейса, которые вы хотите сделать после завершения, должны будут выполняться в главном потоке.

Снова создайте и запустите приложение и выберите цвет или форму для просмотра в приложении. Вы должны увидеть все три цветных изображения для определенной формы или все четыре формы для определенного цвета.

Все ресурсы показаны

Вот как просто использовать ресурсы по требованию. Теперь вы успешно внедрили ресурсы по требованию в приложение.

Важная функция отладки, доступная в Xcode 7, является способностью видеть, какие пакеты актива вы загрузили и какие используются. Чтобы просмотреть это, перейдите к Debug Navigator с запущенным приложением и выберите « Диск» . Вы увидите экран, аналогичный показанному ниже. Ресурсы по запросу — это раздел, который нас интересует.

Отладка ресурсов по требованию

В качестве примера давайте теперь изменим приоритет загрузки, чтобы некоторые ресурсы всегда загружались немедленно. В то же время мы изменим приоритеты сохранения пакетов активов таким образом, чтобы пакеты активов Hexagon и Star очищались перед пакетами активов Circle и Square . Обновите реализацию метода viewDidAppear(_:) как показано ниже.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
     
    request = NSBundleResourceRequest(tags: [tagToLoad])
     
    request.loadingPriority = NSBundleResourceRequestLoadingPriorityUrgent
    NSBundle.mainBundle().setPreservationPriority(1.0, forTags: [«Circle», «Square»])
    NSBundle.mainBundle().setPreservationPriority(0.5, forTags: [«Hexagon», «Star»])
     
    request.beginAccessingResourcesWithCompletionHandler { (error: NSError?) -> Void in
        // Called on background thread
        if error == nil {
            NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
                self.displayImages()
            })
        }
    }
}

После инициализации запроса мы устанавливаем свойство NSBundleResourceRequestLoadingPriorityUrgent в NSBundleResourceRequestLoadingPriorityUrgent . Кроме того, вы можете присвоить этому свойству любое число от 0,0 до 1,0 , чтобы определять приоритет загрузки в вашем приложении.

Преимущество использования этой константы состоит в том, что она автоматически присваивает запросу самый высокий приоритет загрузки, но также игнорирует текущую активность ЦП. В некоторых ситуациях, если ЦП устройства интенсивно используется, загрузка пакета ресурсов может быть отложена.

Далее мы устанавливаем приоритет сохранения для всех четырех тегов формы. Это делается путем вызова setPreservationPriority(_:forTags:) основного пакета приложения. Теперь мы убедились, что если системе ресурсов по требованию необходимо удалить некоторые активы из нашего приложения, пакеты ресурсов Hexagon и Star будут удалены в первую очередь.

Теперь, когда вы знаете, как реализовать ресурсы по требованию в приложении для iOS, я хочу кратко рассказать вам о нескольких лучших практиках, о которых следует помнить.

Помимо сокращения времени загрузки и повышения доступности ваших ресурсов, минимальный размер каждого пакета ресурсов предотвращает чрезмерную очистку системы. Это когда система ресурсов по требованию должна освободить определенное количество места и в итоге освободить намного больше, чем необходимо.

Например, если системе необходимо высвободить 50 МБ пространства и, исходя из условий, упомянутых ранее, было решено, что пакет ресурсов 400 МБ из вашего приложения будет наиболее подходящим для удаления, система излишне очистит 350 МБ. Это означает, что если ваше приложение потеряло больше данных, чем нужно, ему нужно будет снова загрузить все ресурсы, связанные с этим тегом. Рекомендуемый размер для отдельных тегов составляет около 64 МБ.

Если ваше приложение имеет очень предсказуемое взаимодействие с пользователем, лучше начать загрузку ресурсов до того, как они действительно понадобятся. Это должно улучшить работу пользователей, поскольку им не нужно смотреть на экран загрузки, пока ваше приложение загружает контент.

Игры являются распространенным примером. Если игрок только что завершил 5-й уровень, то неплохо бы начать загрузку 7-го уровня, пока он играет 6-го уровня.

Когда вы закончите использовать определенный пакет ресурсов, убедитесь, что либо ваш NSBundleResourceRequest объект освобожден, либо вы вызываете метод endAccessingResources для него.

Это не только позволит избежать превышения приложением лимита в 2 ГБ для используемых ресурсов, но также поможет системе ресурсов по требованию узнать, когда ваше приложение использует эти ресурсы, а это означает, что оно может лучше решить, что нужно удалить, если будет больше места. необходимо.

Недавно я писал о разработке tvOS и в этом руководстве я упомянул об ограничениях приложений tvOS. Максимальный размер пакета приложений составляет 200 МБ, поэтому настоятельно рекомендуется по мере возможности использовать ресурсы по требованию в своих приложениях tvOS.

Из-за сходства tvOS и iOS, API-интерфейсы и лимиты хранения (кроме пакета приложений) для ресурсов по требованию одинаковы. При работе с ресурсами по требованию в tvOS, однако, также важно помнить, что все ресурсы, такие как изображения, имеют одну версию в масштабе 1x, поэтому размер пакетов ресурсов, как показано в XCode, не будет уменьшаться из-за нарезки приложений ,

Ресурсы по требованию в iOS 9 и tvOS — это отличный способ уменьшить размер вашего приложения и предоставить лучший пользовательский опыт людям, которые скачивают и используют ваше приложение. Хотя это очень легко реализовать и настроить, есть немало деталей, которые вы должны иметь в виду, чтобы вся система ресурсов по требованию работала без сбоев, без чрезмерного времени загрузки и ненужной очистки данных.

Как всегда, обязательно оставляйте свои комментарии и отзывы в комментариях ниже.