> Когда использовать weak let, а когда weak var в Swift (iOS, Swift)
Уровень: senior · Роль: mobile · Категория: Технические вопросы
Компании: nuum
Стек: iOS, Swift
> Пример ответа
Короткий ответ
weak let и weak var отличаются по правилам инициализации: weak let требует, чтобы свойство было установлено при инициализации (обычно через init), и после этого его нельзя изменить. weak var можно объявить без начального значения (как weak var delegate: Delegate?), и оно может быть переприсвоено в любой момент. На практике weak let используют для строго обязательных слабых ссылок, которые гарантированно устанавливаются один раз, а weak var - для опциональных делегатов и колбэков, которые могут меняться в рантайме.
Подробное объяснение
В Swift weak - это модификатор, который предотвращает удержание объекта в памяти. Он применим только к ссылочным типам (классам) и только к optional-переменным (или implicitly unwrapped optional). Ключевое отличие let от var здесь - не в слабости, а в изменяемости ссылки.
weak let - это константа, которая хранит слабую ссылку. Она должна быть инициализирована при создании экземпляра (в init или через default value). После инициализации её нельзя переприсвоить. Это создаёт жёсткое инвариантное правило: ссылка либо есть, либо её нет, но она не может "перепрыгнуть" на другой объект.
weak var - это переменная, которую можно объявить без значения (она автоматически становится nil), и которую можно переприсваивать сколько угодно раз. Это стандартный паттерн для делегатов, data source, observer-объектов.
Важный нюанс: weak let не означает, что объект будет жить вечно - он так же освобождается, когда на него нет сильных ссылок. Просто сама ссылка не может быть изменена после установки. Если объект освободился, weak let станет nil, и вы не сможете присвоить ему новый объект.
На практике weak let встречается редко, потому что обычно слабые ссылки нужны именно для изменяемых связей. Но он полезен, когда вы хотите гарантировать, что слабая ссылка не будет случайно переприсвоена - это защита от логических ошибок.
На практике
- Используйте
weak varдля делегатов, data source, колбэков, которые могут быть переустановлены в течение жизни объекта. Это самый частый случай. - Используйте
weak let, когда слабая ссылка устанавливается один раз и не должна меняться. Например, если у вас есть родительский объект, который передаёт себя дочернему, и вы хотите избежать retain cycle, но при этом дочерний объект не должен менять родителя. weak letтакже удобен в замыканиях, когда вы захватываетеselfслабо - тамletнеявно подразумевается, и вы не можете использоватьvarв capture list.- Не используйте
weak letдля свойств, которые могут бытьnilв момент инициализации - компилятор заставит вас либо сделатьvar, либо использовать!(implicitly unwrapped), что опасно.
Пример кода
SWIFTfinal class Parent {var child: Child?}final class Child {// Делегат может меняться - используем weak varweak var delegate: Parent?// Родитель устанавливается один раз - weak letweak let parent: Parentinit(parent: Parent) {self.parent = parent}}// Использованиеlet parent = Parent()let child = Child(parent: parent)parent.child = childchild.delegate = parent// Если parent освободится:// child.parent == nil (weak let автоматически обнуляется)// child.delegate == nil (weak var тоже)
Как отвечать на собеседовании
Начните с главного различия: let vs var - это изменяемость ссылки, а не слабость. Затем объясните, что weak let требует обязательной инициализации и не может быть переприсвоен, а weak var - опционален и изменяем. Приведите примеры: делегаты - это weak var, а одноразовые связи - weak let. Подчеркните, что weak let - редкий паттерн, и его основная ценность - защита от случайного переприсваивания. Упомяните, что в capture list замыканий weak всегда подразумевает let, и это неявное использование.
Что проверяет интервьюер
Интервьюер проверяет понимание семантики weak и let/var в Swift, а не просто заученные правила. Он хочет увидеть, что вы понимаете жизненный цикл объектов, retain cycle и разницу между изменяемой и неизменяемой ссылкой. Также важно, что вы знаете ограничения: weak работает только с классами и optional, и что weak let требует инициализации. Это проверка глубины понимания ARC и дизайна API.
Типичные ошибки
- Утверждение, что
weak let- это то же самое, чтоweak var, только для констант - это верно, но недостаточно, потому что упускается обязательность инициализации. - Использование
weak letдля свойств, которые могут бытьnilпри создании - компилятор выдаст ошибку, и кандидат не понимает, почему. - Путаница с
unowned- некоторые говорят, чтоweak letэквивалентенunowned, но это не так:weak letобнуляется при освобождении объекта, аunowned- нет. - Попытка переприсвоить
weak letв коде - это ошибка компиляции, и кандидат должен это знать. - Игнорирование того, что в замыканиях
weakвсегдаlet- если кандидат говорит, что можно использоватьweak varв capture list, это ошибка.
> Похожие задачи по mobile
Как организована сборка приложения
Когда создается таблица виртуальных методов и протокольная таблица в Swift
В каком порядке вызываются defer блоки в Swift
Что значит слово self в SwiftUI
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью