Что такое замыкания и какие бывают виды в Swift
Что проверяют
Знание не столько синтаксиса, сколько семантики захвата: замыкание в Swift это ссылочный тип, захват по умолчанию сильный, и отсюда растут циклы удержания. Ждут корректную классификацию, а не пересказ примеров.
Как отвечать
Замыкание это самодостаточный блок кода, который передают как значение. Формально к замыканиям относятся три формы: глобальные функции, вложенные функции и безымянные closure expressions; первые ничего не захватывают, остальные захватывают окружение.
Классификация, которую обычно хотят услышать, идёт по атрибутам и по способу захвата. Параметр-замыкание по умолчанию non-escaping и не может пережить вызов функции. Пометка @escaping нужна, когда замыкание сохраняется в свойство, кладётся в массив колбэков или уходит в асинхронную операцию, и именно там требуется явное указание себя. Пометка @autoclosure заворачивает выражение аргумента в замыкание и даёт ленивое вычисление, как у правого операнда оператора объединения с nil. Отдельно называют trailing closure, сокращённые имена аргументов и список захвата.
loader.load { [weak self] result in
guard let self = self else { return }
self.render(result)
}Где спотыкаются
Ставят слабую ссылку на себя во всех замыканиях подряд. В non-escaping замыканиях вроде map, filter или блока анимации цикл удержания невозможен, и лишняя пометка только зашумляет код и добавляет разворачивание опционала.
Берут unowned там, где объект реально может исчезнуть раньше вызова. Это не оптимизация, а обмен мягкого выхода на падение приложения; unowned оправдан, только когда время жизни гарантировано.
Считают, что список захвата копирует объект. Копируется ссылка, поэтому состояние остаётся общим, а изменения видны внутри. Сюда же относится вера в то, что замыкание ведёт себя как значение: присвоили в две переменные, обе указывают на один блок с одним захваченным состоянием.