Сколько объектов минимум нужно для создания retain cycle в Swift?
Что проверяют
Понимаете ли вы, что цикл удержания это замкнутая цепочка сильных ссылок, а не обязательно пара объектов. Правильный ответ: хватит одного. Вопрос с подвохом, и за ним сразу идут уточнения про weak и unowned и про то, как найти утечку в Xcode.
Как отвечать
- один объект: экземпляр класса держит сильную ссылку на самого себя. После
node.next = nodeсчётчик ссылок уже не опустится до нуля, иdeinitне вызовется; - объект и замыкание: самый частый случай на практике. Класс хранит замыкание в свойстве, а замыкание сильно захватывает
self, напримерonUpdate = { self.reload() }. В коде это один ваш объект, в памяти второй участник цикла это контекст замыкания в куче; - два объекта: классика с делегатом без
weakили parent и child, которые хранят друг друга.
Разрывают цикл так:
weak: ссылка не увеличивает счётчик, всегда опциональная и обнуляется, когда объект освобождён. Для делегатов пишутweak var delegate, а протокол ограничиваютAnyObject;unowned: тоже не держит объект, но и не обнуляется. Обращение после освобождения приводит к крашу, поэтому годится, только если объект гарантированно живёт дольше ссылки;- список захвата:
[weak self]в замыкании иguard let self else { return }внутри.
Проверять себя стоит через deinit с логом, Debug Memory Graph в Xcode и Instruments с шаблоном Leaks.
Где спотыкаются
Уверенно отвечают «два» и не рассматривают ссылку объекта на самого себя. Интервьюер именно этого и ждёт.
Ставят [weak self] вообще в каждое замыкание, включая UIView.animate и DispatchQueue.main.async. Там цикла нет: замыкание выполняется один раз и в объекте не хранится. Лишний weak не вреден, но показывает, что механизм не понят.
Ищут цикл только между своими классами. Между тем Timer.scheduledTimer(timeInterval:target:selector:userInfo:repeats:) сильно держит target, а блок из NotificationCenter.addObserver(forName:object:queue:using:) хранится центром уведомлений, пока наблюдатель не удалён. Если блок захватил self сильно, объект не освободится.