Как система понимает, когда можно очистить память в iOS?
Что проверяют
Понимание того, что в iOS нет сборщика мусора и нет свопа для памяти приложения: освобождение объектов детерминировано, а системная «очистка памяти» это jetsam, который просто убивает процессы. Разговор про уровень объекта и уровень процесса надо разделять.
Как отвечать
Уровень объекта, ARC. Компилятор на этапе сборки расставляет retain и release, объект освобождается ровно в момент, когда счётчик ссылок падает до нуля. Это не сборка мусора: нет пауз, нет обхода графа, нет обнаружения циклов. Цикл сильных ссылок это утечка навсегда, лечится weak и unowned (делегаты, [weak self] в замыканиях и таймерах).
Уровень процесса, jetsam. Своп для памяти приложения отсутствует. Грязные страницы (heap, декодированные изображения) остаются резидентными, чистые страницы, замапленные с диска, могут вытесняться и подгружаться заново. Когда памяти мало, memorystatus убивает процессы по приоритету: сначала фоновые и самые прожорливые, приостановленные следом, активное foreground-приложение последним. Убийство приходит как SIGKILL, никакого applicationWillTerminate при этом не будет, поэтому состояние сохраняют при уходе в фон.
Сигналы, которые приложение получает до этого:
didReceiveMemoryWarning()уUIViewControllerиUIApplication.didReceiveMemoryWarningNotificationдля остальных;DispatchSource.makeMemoryPressureSource(eventMask: [.warning, .critical])для слоёв без UI;NSCacheумеет сам выбрасывать содержимое под давлением памяти, обычныйDictionaryне умеет.
Ни один сигнал не гарантирован: при резком скачке потребления процесс убьют, ничего не прислав.
Что делать разработчику:
- по предупреждению отпускать восстановимое: кэши, декодированные картинки, данные невидимых экранов. Не освобождать то, что потом нельзя воссоздать;
- изображения даунсэмплить при загрузке. В памяти лежит распакованный битмап размером примерно ширина на высоту на 4 байта, и он не зависит от того, был файл HEIF, WebP или PNG: формат экономит диск и трафик, но не RAM. Правильный инструмент это
CGImageSourceCreateThumbnailAtIndexсkCGImageSourceThumbnailMaxPixelSize; - крупные файлы читать через отображение в память:
Data(contentsOf:options:.mappedIfSafe). Такие страницы чистые и вытесняются без убийства процесса; - мерить в Instruments (Allocations, Leaks, VM Tracker) и Memory Graph Debugger, ориентироваться на footprint, а не на цифру в навигаторе Xcode.
Где спотыкаются
Описывают ARC как сборщик мусора, который «сам находит ненужные объекты», и заодно уверены, что перевод картинок в HEIF снижает потребление оперативной памяти.