Для обнаружения и устранения утечек памяти использовал следующие инструменты и подходы:
-
Инструмент Allocations в Instruments:
- Запускал приложение через Product -> Profile -> Allocations.
- Следил за ростом количества объектов (Persistent Objects) или общего объема занятой памяти (Overall Bytes) при повторяющихся действиях пользователя (например, навигация по экранам туда-обратно).
- Использовал фильтры для поиска специфических классов, количество экземпляров которых аномально растет.
- Глубоко анализировал стек вызовов для создания каждого экземпляра, чтобы определить, где именно происходит удержание объекта.
-
Инструмент Leaks в Instruments:
- Запускал приложение через Product -> Profile -> Leaks.
- Убеждался, что инструмент обнаруживает утечки памяти, автоматически сканируя хип.
- Анализировал список обнаруженных утечек, включая стек вызовов для их возникновения, чтобы понять, какой объект или блок памяти не освобождается.
-
Отладчик Xcode (Debug Memory Graph):
- В процессе работы приложения в Xcode, нажимал на кнопку "Debug Memory Graph" в панели отладки.
- Визуализировал граф объектов в памяти.
- Искал циклические ссылки (strong reference cycles), отображаемые в виде петель на графе.
- Выбирал подозрительные объекты и инспектировал их ссылки, чтобы понять, кто их удерживает.
-
Анализатор в Xcode (Product -> Analyze):
- Запускал статический анализ кода для выявления потенциальных проблем с управлением памятью, включая возможные утечки, до запуска приложения.
- Обращал внимание на предупреждения, связанные с ARC (Automatic Reference Counting), например, потенциальные циклические ссылки (retain cycles).
-
Code Review:
- Проводил или участвовал в ревью кода, уделяя особое внимание местам, где могут возникать циклические ссылки:
- Делегаты с
strong ссылками вместо weak или unowned.
- Замыкания, захватывающие
self без использования weak или unowned.
- Объекты, которые одновременно являются источником данных и делегатом для другого объекта.
-
Устранение утечек:
- Циклические ссылки: В большинстве случаев утечки вызваны циклическими strong-ссылками. Устранял их, делая одну из ссылок
weak или unowned там, где это логически корректно (например, родитель должен удерживать дочерний элемент сильно, а дочерний элемент не должен сильно удерживать родителя или делегата).
- Замыкания: Использовал
[weak self] или [unowned self] в начале замыканий, чтобы избежать сильного захвата self, особенно в асинхронных операциях или колбэках.
swift
- Делегаты: Убеждался, что ссылки на делегатов объявлены как
weak.
swift
-
Тестирование: После исправления потенциальных утечек, повторно использовал Instruments и Debug Memory Graph, чтобы убедиться, что проблема решена и новые утечки не появились. В некоторых случаях писал юнит-тесты для проверки освобождения объектов.