Неприятные Аспекты Работы С Images.xcassets: Размер И Память

Добрый день, уважаемые жители Хабро! Images.xcassets делает много приятных вещей, мне особенно нравится нарезка и возможность добавлять отдельное изображение для каждого типа устройства.

Поэтому, начиная новый проект, я, даже не задумываясь, создаю Images.xcassets, добавляю туда значки и заставки, а потом закидываю туда все новые ресурсы.

Сегодня я узнал пару неприятных вещей о xcassets, это заставило меня отказаться от него и потратить пару часов на переделку проекта.

Не самое приятное и полезное занятие.

Если хотите учиться на чужих ошибках, пожалуйста, под кат.



Немного предыстории
С группой энтузиастов я начал делать сказки для детей на iPad. Я заранее понимаю, что на этом вы не разбогатеете, наша цель - хорошее приложение, работающее на всех устройствах с iOS 8. Также мы хотели избежать до боли знакомой ситуации - вы скачали приложение, запустили его и узнаете что для работы необходимо загрузить еще > 100 МБ.

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

Книга содержит иллюстрации в формате jpeg, без сжатия самая маленькая книга весит 82Мб, остальные 100+Мб.

Это значит, что если мы хотим оставить возможность скачивания через 3g, то у нас остается 18Мб на приложение.

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

С этими исходными данными я создал проект xcode.

Первая битва за память
Когда я начинал проект, единственным тестовым устройством, которое у меня было, был iPad Air. На нем все летает, скажем честно, это плохой выбор для тестирования.

Поэтому ближе к концу проекта я приобрел iPad mini 1 gen — устройство без retina и с процессором A5, но на нем установлена iOS 8, а затем и iOS 9. При отладке приложения я получил предупреждение о нехватке памяти.

временами.

Это не нормально, так не должно быть.

Открываю вкладку «Отладка» и вижу, что приложение израсходовало 100 Мб.

И это при том, что я ничего особенного не делал, просто открыл приложение и в навигационном стеке было всего 3 контроллера.

Открываю профайлер и вижу, что 70Мб занято картинками.

100 МБ на iPad mini — это явно слишком много.

Поэтому пришлось пойти и добавить большое количество изображений с масштабом 1х (раньше я их не добавлял, зная, что для Neretina iOS сама мне их подготовит), это по идее не большой удар по размеру приложения, но это резко уменьшит объем используемой памяти.

В итоге у меня получилось 47Мб.

На мой взгляд, это пока неоправданно, но предупреждения по памяти перестали приходить.



Борьба за размер
И вчера я закончил разработку приложения.

Конечно, еще остались TODO, и ребята потестируют и, возможно, что-то найдут, но первый этап уже позади.

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

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

Шаг 1. Посмотрите, что занимает так много места Беру build.ipa, переименовываю в build.zip, разархивирую и смотрю содержимое build.app. Нахожу файл Assets.car, который весит 53Мб.

В принципе, размер приложения можно объяснить - 80+53+ подробно.

Я понимаю, что просто так открыть его не смогу, поэтому решил сам посмотреть Images.xcassets в проекте.

Весит всего 38Мб.

Что это происходит? Туда что-то положили на 16Мб, но видимо забыли мне об этом сказать.

Шаг 2 - что они туда добавили? Быстрый поиск в Интернете дает мне автомобильный инструмент , чтобы просмотреть Assets.car. Делаю все по инструкции — собираю проект, беру собранный картул и запускаю на своем Assets.car. Смотрю, что у меня получилось в итоге - 130 файлов общим размером 41,5Мб и, если я могу списать 3,5Мб в pngcrush, то куда делись 11,5Мб? Повторяю быстрый поиск в сети.

Я нахожу подобные проблемы, например, здесь .

И почему я плачу из-за каких-то 29%, размер вообще увеличился в 6 раз.

Но это не мой случай — все мои изображения в формате PNG, так как почти все изображения имеют области прозрачного фона.

Я уже не находил надежды исправить эту ситуацию.

Я проверяю еще раз Документация Apple — сделали бинарный файл для ускорения загрузки приложения.

Как по мне, скорость загрузки напрямую зависит от размера.

Поэтому я решил удалить все картинки из Images.xcassets и добавить их в проект по старинке.

Мне пришлось сделать нарезку в нескольких местах кода, используя

  
   

- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets

С помощью таких махинаций мне удалось уменьшить размер приложения со 142Мб до 131Мб.

Я обязательно продолжу оптимизировать ресурсы в приложении, но 10Мб за отказ от Images.xcassets - это уже неплохо.

Шаг 3 – что случилось с памятью? Запустил на iPad mini - 23Мб против 47Мб.

На iPad Air 66Мб против 100Мб.

Заключение Может показаться, что разница между 142Мб и 131Мб невелика.

А ведь это очень существенный показатель без ухудшения качества снимков и прочих хитростей.

Это существенный шаг к порогу 100 МБ и доступности приложения в сетях 3G. А уменьшение памяти при использовании приложения - очень приятный бонус.

Особой разницы при запуске приложения я не заметил.

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

И впоследствии проблем со скоростью работы не возникло, так как в приложении много неторопливой анимации и падения производительности заметить невозможно.



P.S.
Я знаю, что с iOS 9 все должно обмен и Apple предоставит только тот контент, который необходим для данного устройства.

Но даже когда я удалил все 1х изображения, размер сборки стал 135. При этом я пожертвовал памятью на не retina устройствах и качеством изображения, которое заметно невооруженным глазом на некоторых элементах интерфейса.



P.S.S.
Поскольку речь здесь идет о памяти, хотелось бы поделиться еще одним интересным фактом.

Я всегда создаю изображения с

+ (UIImage *)imageNamed:(NSString *)name;

Быстрый и удобный метод, имеющий побочные эффекты.

Когда пользователь отправляет приложение в фон, система вполне может выкинуть изображение из памяти (а на iPad mini она всегда так делает), ведь она точно знает, что это изображение взято из Bundle, и оно вероятно, все еще там.

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

Звучит вполне логично и целесообразно.

Однако это может вызывать лаги при открытии приложения в фоновом режиме, которых не было даже при холодном запуске приложения.

В моем случае это была карусель, и она лагала только тогда, когда приложение поднималось из фона.

Всем хороших выходных и поменьше таких неприятных сюрпризов.

Теги: #xcode #iOS #xcassets #Разработка для iOS #objective-c #xcode

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.