> Когда использовать 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), что опасно.

Пример кода

SWIFT
final class Parent {
var child: Child?
}
final class Child {
// Делегат может меняться - используем weak var
weak var delegate: Parent?
// Родитель устанавливается один раз - weak let
weak let parent: Parent
init(parent: Parent) {
self.parent = parent
}
}
// Использование
let parent = Parent()
let child = Child(parent: parent)
parent.child = child
child.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, это ошибка.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью