Что такое zombie object
Что проверяют
Понимаете ли вы, что зомби это не баг, а инструмент отладки, и различаете ли обращение к освобождённой памяти и цикл сильных ссылок. У iOS-разработчика эти две беды лечатся по-разному, а путают их постоянно.
Как отвечать
Зомби-объект это подменыш, который остаётся на месте освобождённого объекта, когда включена диагностика Zombie Objects. Без неё обращение к деаллоцированной памяти даёт падение по случайному адресу: память могла быть уже переиспользована, и приложение валится не там, где ошибка. С диагностикой рантайм не отдаёт память обратно, а превращает объект в экземпляр служебного класса, который на любое сообщение печатает имя исходного класса и селектор.
Включается в схеме проекта: Edit Scheme, вкладка Run, раздел Diagnostics, галка Zombie Objects. Работает только для наследников NSObject, то есть для Objective-C и для Swift-классов, унаследованных от NSObject. Чистые Swift-классы так не ловятся, для них берут Address Sanitizer.
Откуда берутся обращения к мёртвому объекту в Swift: ссылка unowned, пережившая владельца, небезопасные варианты вроде unowned(unsafe) и Unmanaged, указатели, отданные в C-API, неснятые наблюдатели и таймеры. В обычном коде на ARC со strong и weak такого не случается: weak обнуляется сам.
Где спотыкаются
Говорят, что зомби лечится weak-ссылками, потому что weak спасает от циклов. Цикл сильных ссылок это утечка, объект живёт вечно; зомби это противоположная беда, обращение к уже мёртвому. Weak тут помогает не тем, что разрывает цикл, а тем, что обнуляется.
Оставляют диагностику включённой в замерах производительности и в схеме релиза. Память при ней не возвращается вовсе, потребление растёт, и любые цифры по памяти теряют смысл; это режим исключительно для отладочного запуска.
Путают unowned и weak. Первое обещает рантайму, что объект переживёт ссылку, и при нарушении обещания даёт ровно такое падение. Если время жизни не гарантировано, берётся weak с опциональной проверкой.