Что такое ARC и для чего он нужен
Что проверяют
Понимаете ли вы, откуда в Swift берутся утечки памяти и чем ARC отличается от сборщика мусора. Определение знают все, поэтому почти сразу просят показать цикл сильных ссылок в замыкании и объяснить разницу между weak и unowned.
Как отвечать
ARC (Automatic Reference Counting) это подсчёт ссылок, который расставляет компилятор. Вызовы retain и release вставляются на этапе компиляции, отдельного сборщика и пауз в рантайме нет: объект освобождается в момент, когда исчезает последняя сильная ссылка, и тут же вызывается deinit.
Что важно назвать:
- область действия: экземпляры классов и замыкания. Структуры и перечисления копируются по значению, но ссылки на классы внутри них тоже считаются;
- strong: ссылка по умолчанию, увеличивает счётчик;
- weak: счётчик не увеличивает и при освобождении объекта сама становится
nil, поэтому всегдаOptionalиvar. Типичное место:weak var delegate; - unowned: тоже не держит объект, но не обнуляется, обращение после освобождения приводит к крашу. Подходит, когда ссылка гарантированно живёт не дольше владельца;
- список захвата:
[weak self]в замыкании, которое хранит сам объект, разрывает циклself → closure → self.
Где циклы появляются на практике: замыкания в свойствах, подписки Combine через sink, Timer с блоком или таргетом, делегаты без weak. Искать утечки удобно через Memory Graph Debugger в Xcode и инструмент Leaks в Instruments.
Для полноты: изменение счётчика атомарное, поэтому сам подсчёт потокобезопасен, но само свойство от гонок это не защищает.
Где спотыкаются
Называют ARC сборщиком мусора. Сборщика нет, и циклы ARC не находит, в отличие от трассирующего GC в Java.
Пишут [weak self] везде, включая UIView.animate и DispatchQueue.main.async. Такие замыкания объект не хранит, цикла нет, а лишний guard let self только усложняет код.
Выбирают unowned ради отсутствия опционала там, где объект может умереть раньше, например в сетевом колбэке. Результат: краш вместо тихого nil.