TGViewer
iOS Dev iOS Dev @iosdev · 7.92K subscribers
Post #537 4.04K
Почему ваша картинка размером в 2 мегабайта может отъедать 80 мб памяти? Сейчас разберёмся.
Или как пофиксить одну из причин out of memory exception

На собеседованиях часто просят отобразить ленту из картинок, взятых откуда-нибудь из стороннего ресурса, гугла, например, условного unsplash или откуда-нибудь ещё. Скорее всего, и у инженеров на боевых проектах рано или поздно может возникнуть подобная задача.

Одна из потенциальных сложностей, с которой можно столкнуться при такой задаче — out of memory exception. Так в чём же дело?

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

Главное, что нужно запомнить, использование памяти ≠ размеру файла. И вот почему.

Использование памяти связано с размерами изображения, а не с размером файла (Session 416, WWDC 2018).

Всё дело в том, что для отображения изображения на экране, iOS сначала необходимо декодировать и распаковать изображение. Обычно 1 пиксель декодированного изображения занимает 4 байта памяти — 1 байт для красного, 1 байт для зеленого, 1 байт для синего и 1 байт для альфа-канала (да-да, тот самый RGB с альфой). Например:

(3648 * 5472) * 4 bytes ≈ 80MB

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

Что со всем этим делать?

Разработчики в этой статье пробовали менять масштаб и перерисовать изображение, но это не помогло. Это связано с тем, что операции для изменения размера для UIImage дороги. В процессе изменения размера iOS по-прежнему будет декодировать и распаковывать исходное изображение, вызывая нежелательный скачок памяти.

Одно из решений, которым делятся инженеры Apple — юзать даунсэмплинг.

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

Флаги, которые можно использовать

1️⃣ kCGImageSourceShouldCache — когда для этого флага установлено значение false, мы сообщаем основному фреймворку, что нам нужно только создать ссылку на источник изображения и не хотим декодировать изображение сразу при создании объекта CGImageSource.

В ситуации, когда у вас нет доступа к пути к источнику изображения, вы можете создать объект CGImageSource, используя инициализатор CGImageSourceCreateWithData().

2️⃣ kCGImageSourceShouldCacheImmediately — этот флаг указывает, что декодировать изображение нужно именно в тот момент, когда мы запускаем процесс понижения дискретизации.

3️⃣ kCGImageSourceCreateThumbnailWithTransform — установка этого флага в значение true очень важно для сохранения исходной ориентации.

Подводные камни (а как же без них)

Имейте в виду, что даунсэмплинг — это процесс, который потребляет ресурсы процессора. Таким образом, по-прежнему предпочтительнее использовать правильно масштабированный источник изображения, а не понижать дискретизацию HD-изображения. Другими словами, вы должны использовать даунсэмплинг только тогда, когда вам нужно отобразить изображение, размер которого намного превышает требуемый размер на экране.

Важные моменты

⚪ Помните, что память — это конечный и общий ресурс.

⚪ Используйте встроенный в Xcode мониторинг.

⚪ Позвольте iOS выбрать ваши форматы изображений, когда это возможно.

⚪ Используйте ImageIO для понижения разрешения изображений (помните про подводные камни).

⚪ Выгружайте крупные ресурсы, которые находятся за пределами экрана.

⚪ Не игнорируйте графики памяти (memory graphs), чтобы лучше понять, что происходит.

Что почитать ещё?

📖 Deep Dive into iOS Memory.
📖 Reducing Memory Footprint When Using UIImage.
📺 Session 416, WWDC 2018.
🔗 https://developer.apple.com/documentation/imageio/cgimagesource.

@iOS Dev — отвечаем на вопросы.
Apple Developer iOS Memory Deep Dive - WWDC18 - Videos - Apple Developer Discover how memory graphs can be used to get a close up look at what is contributing to an app's memory footprint. Understand the true...
  • 🔥 36
  • 👍 13
  • 🏆 6
  • ❤ 2
  • 👏 1
More from @iosdev
  1. Oct 1, 2026SwiftUI Charts и динамическое маскирование Одним из применений для диаграмм является разны…
  2. Sep 29, 2026⚡️Сегодня ночью десятки тысяч приложений массово начали крашиться из-за либы для аналитики…
  3. Sep 28, 2026От pbxproj к xcproj: разбор конфигураций проекта 📖 В этой статье можно посмотреть на новы…
  4. Sep 25, 2026Симулятор iPhone Duo: тестирование и оптимизация приложения Как только был анонсирован iPh…
  5. Sep 24, 2026Настоящая причина, почему на презентации не показали, как выглядит звонок с iPhone Duo. 😃…
  6. Sep 23, 2026Работа с тулбарами на iPhone Duo На iPhone Duo элементы управления навигацией, тулбар-экшн…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →