Добрый день, уважаемые жители Хабро! 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 и добавить их в проект по старинке.
Мне пришлось сделать нарезку в нескольких местах кода, используя
С помощью таких махинаций мне удалось уменьшить размер приложения со 142Мб до 131Мб.- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets
Я обязательно продолжу оптимизировать ресурсы в приложении, но 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
-
Hr-Портал - Продолжение
19 Oct, 24 -
Большой Брат Может Ограждать Сеть
19 Oct, 24 -
Черная Пятница Для Хостинг-Провайдеров
19 Oct, 24 -
Самые Интересные Блоги И Сайты По C#/.Net
19 Oct, 24