В каком случае `weak` ссылка в Swift станет `nil`?

«В каком случае `weak` ссылка в Swift станет `nil`?» — вопрос из категории Управление памятью, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

weak ссылка автоматически становится nil, когда объект, на который она указывает, деаллоцируется системой управления памятью (ARC). Это основной механизм для разрыва сильных циклов ссылок без риска краша.

Пример с циклом и делегатом:

protocol DataLoaderDelegate: AnyObject { // Протокол должен быть class-bound
    func dataLoadingDidFinish()
}

class DataLoader {
    weak var delegate: DataLoaderDelegate? // 1. Слабая ссылка на делегата
    func loadData() {
        // Загрузка данных...
        delegate?.dataLoadingDidFinish() // 2. Безопасный вызов через опционал
    }
}

class ViewController: UIViewController, DataLoaderDelegate {
    let loader = DataLoader()

    override func viewDidLoad() {
        super.viewDidLoad()
        loader.delegate = self // 3. Устанавливаем себя делегатом
        loader.loadData()
    }

    func dataLoadingDidFinish() {
        print("Data loaded!")
    }
}

// Сценарий:
// 1. ViewController сильно ссылается на DataLoader (свойство `loader`).
// 2. DataLoader слабо ссылается на ViewController (свойство `delegate`).
// 3. Когда пользователь закрывает экран, ViewController деаллоцируется.
// 4. Сразу после этого свойство `loader.delegate` автоматически становится `nil`.
// Цикл сильных ссылок не образовался, утечки памяти нет.
Ключевые отличия weak от unowned: weak unowned
Всегда опциональна (var). Неопциональна (let или var).
Безопасно обнуляется. При обращении к деаллоцированному объекту — краш.
Используется, когда время жизни ссылаемого объекта может быть короче. Используется, когда время жизни ссылаемого объекта точно больше или равно.