> В чем разница между weak и unowned ссылками в Swift и когда их использовать (iOS, Swift)
Уровень: senior · Роль: mobile · Категория: Технические вопросы
Компании: Wildberries, SimbirSoft, nuum, VK, Bip.ru, Doubletapp, Совкомбанк, Masterdata, Тинькофф, Eltex, Яндекс
Стек: iOS, Swift
> Пример ответа
Короткий ответ
Weak и unowned - оба варианта позволяют избежать retain cycle в замыканиях и свойствах. Weak всегда optional и автоматически становится nil при освобождении объекта, требует weak var. Unowned - non-optional, предполагает, что объект живёт столько же, сколько ссылка, при обращении к освобождённому объекту - crash. Weak используем для делегатов и ссылок, которые могут стать nil. Unowned - когда время жизни ссылки гарантированно не превышает время жизни объекта.
Подробное объяснение
Разница в семантике владения и безопасности. Weak ссылка - это слабая ссылка, которая не увеличивает счетчик ссылок. ARC автоматически обнуляет её (nil) при деинициализации объекта. Поэтому weak объявляется только как var и всегда optional. Unowned также не увеличивает счетчик, но не обнуляется - она остаётся "висячей" (dangling) после освобождения объекта. Обращение к unowned после деинициализации вызывает runtime crash.
Ключевое различие - гарантия времени жизни. Weak говорит: "объект может умереть в любой момент, я готов к nil". Unowned говорит: "объект гарантированно жив, пока я существую". На практике это означает: если есть хоть малейший шанс, что объект освободится раньше, чем ссылка - используй weak. Если уверен в порядке жизни - unowned чуть более эффективен (без unwrapping) и выражает намерение.
В замыканиях выбор зависит от capture list. Если замыкание может пережить захваченный объект - weak. Если замыкание и объект живут в одном жизненном цикле (например, замыкание - свойство того же класса) - unowned допустим, но weak безопаснее.
На практике
Для делегатов и data source - всегда weak. Для замыканий, хранящихся в свойствах класса, - чаще weak, потому что сложно гарантировать порядок деинициализации. Unowned оправдан в редких случаях: например, когда замыкание вызывается синхронно внутри метода того же объекта, или когда объект гарантированно живёт дольше замыкания (например, замыкание - свойство дочернего объекта, который удаляется раньше родителя).
В SwiftUI и Combine unowned встречается в sink, но там лучше weak из-за асинхронности. В GCD-замыканиях - только weak, потому что замыкание может выполниться после освобождения объекта. В циклах с двумя объектами, где один владеет другим, а второй ссылается на первого - weak на обратную ссылку.
Пример кода
SWIFTclass Child {var onEvent: (() -> Void)?deinit { print("Child deinit") }}class Parent {var child: Child?weak var weakRef: Child?unowned var unownedRef: Child!func setup() {let c = Child()child = cweakRef = cunownedRef = c // опасно: unowned на объект, которым владеет другой}func testClosure() {child?.onEvent = { [weak self] inguard let self else { return }print(self)}// или [unowned self] - только если self точно жив}}
Как отвечать на собеседовании
Начни с главного: оба не увеличивают retain count, разница в безопасности и optional. Приведи конкретный сценарий: делегат - weak, потому что владелец может освободиться. Замыкание в свойстве - weak, потому что жизненный цикл непредсказуем. Unowned - только когда есть железная гарантия. Покажи понимание retain cycle и ARC. Упомяни, что weak требует var и optional, а unowned - нет. Если спросят про производительность - weak чуть дороже из-за обнуления, но это микрооптимизация.
Что проверяет интервьюер
- Понимание ARC и механизма подсчёта ссылок
- Умение анализировать жизненный цикл объектов
- Знание синтаксических ограничений (weak - var optional, unowned - non-optional)
- Практический опыт: когда реально возникает retain cycle
- Понимание разницы между "может стать nil" и "не может стать nil" в контексте безопасности
- Способность объяснить trade-off между безопасностью и производительностью
Типичные ошибки
- Использование unowned там, где объект может освободиться - crash
- Объявление weak как
let- компилятор не позволит - Забывание
guard let selfв weak-замыканиях - Утверждение, что unowned "быстрее" - это не причина выбора
- Использование weak для value types - бессмысленно
- Путаница между unowned и weak в контексте замыканий: если замыкание хранится в свойстве объекта и захватывает self - это retain cycle, weak обязателен
- Игнорирование случая, когда объект деинициализируется, но unowned ссылка остаётся - это UB, а не просто nil
> Похожие задачи по mobile
Что такое принцип разделения интерфейса (Interface Segregation Principle)
Ты сейчас в активном поиске работы
Какой жизненный цикл у UIViewController и в каком порядке вызываются методы
Какие паттерны проектирования вы знаете и использовали в работе
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью