ViewController — это один из компонентов, где обычно происходит утечка памяти, поскольку именно он чаще всего используется для хранения множества частей кода вместе. Одна ошибка, и в итоге вы получаете утечку.
Apple предлагает отличный инструмент для отладки утечек памяти. Часто для этого используется метод print в deinit.
deinit {
print("deinit (self)")
}
Если произошла утечка, deinit не будет вызван, и ничего не будет выведено. Даже если это не очень хорошо выглядит, это вполне рабочий вариант.
Примечание
Если вы найдёте статью интересной, то в этом канале я пишу об iOS-разработке.
Более качественный способ
Можно использовать Symbolic breakpoint, чтобы обнаружить retain cycles для UIViewController. Это та же концепция, что print выше, но гораздо чище. Таким образом, вы не накидываете в код лишние print.
Простая инструкция
Перейдите в Breakpoint Navigator (меню View > Navigators > Show Breakpoint Navigator или ⌘ - command + 8). Кстати, для шорткатов можно использовать и это решение: вот оно.
Нажмите + и выберите Symbolic Breakpoint... or Menu Debug > Breakpoints > Create Symbolic Breakpoint...
Установите для
Symbol
значение-[UIViewController dealloc]
Нажмите кнопку Add Action и установите звук
Sound
в (ну или любой другой, какой посчитаете нужным).Добавьте ещё одно действие, нажав +.
-
Установите действие на Log Message и задайте сообщение, которое вы хотите вывести в консоль, когда сработает dealloc для View Controller. В моем случае я установил его в --- dealloc @(id)[
Отметьте опцию Automatically continue after evaluating actions, поскольку мы не хотим, чтобы дебаггер останавливался, когда сработает наш Symbolic Breakpoint.
Обнаружение утечки
С установленным брейкпоинтом всякий раз, когда для UIViewController сработает
dismiss
, или, например,pop
из навигационного стека, вы услышите соответствующий звук и увидите лог в консоли. Это означает, что все работает именно так, как ожидалось.Если вы выводите или удаляете
ViewController
, но не слышите соответствующего звука, это означает только одно — произошла утечка.Итак, что потребуется для обнаружения утечек
Symbol
— [UIViewController dealloc]Module
— пустой или UIKitCoreAction:Sound
— pop или любой другой звукAction: Log Message
— --- dealloc @(id)[" class="formula inline">arg1 description]@ или любое другое сообщениеOptions
— можно установить Automatically continue after evaluating actionsПримеры
Если вы нашли что-то полезное для себя, то подписывайтесь на мой канал, тут больше интересных историй и подходов.
Комментарии (3)
Gargo
26.04.2022 13:49+1этот трюк работает не всегда. Иногда какой-нибудь объект удерживает в памяти один view controller, а релизит другой. Мне попадались такие случаи:
1)объект удерживает в памяти последний view controller, приложение релизит предпоследний view controller (если такой есть)
2)объект удерживает в памяти первый view controller, приложение релизит все остальные view controllers
Если применять способ из статьи, то придется следить за всем жизненным циклом view controller'а, потому что ошибка проявится только в самом начале.
aamonster
Не понял, зачем автор использует этот трюк. Выглядит так, будто просто чтобы убедиться, что утечка действительно есть. Не ищется ни место утечки (проверяем конкретный объект), ни её причина (где список других объектов, удерживающих наш)?
Ну и отмечу, что удобнее просто использовать Instruments в XCode
AlexWoodblock
А еще symbolic breakpoints, если правильно помню, весьма медленные.