Почему аутлеты (IBOutlet) в UIViewController могут оказаться nil?

«Почему аутлеты (IBOutlet) в UIViewController могут оказаться nil?» — вопрос из категории UIKit, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Аутлеты (@IBOutlet) остаются nil, когда связь между кодом и элементом интерфейса в Storyboard/XIB не установлена или разорвана.

Распространенные причины:

  1. Отсутствует аннотация @IBOutlet в коде.

    // ОШИБКА: Свойство не помечено как IBOutlet
    var myLabel: UILabel?
    
    // ПРАВИЛЬНО: Связь может быть установлена
    @IBOutlet weak var myLabel: UILabel!
  2. Нет связи в Interface Builder. Элемент на storyboard не подключен к свойству в коде (или подключен к другому свойству).

  3. Несоответствие имен. Имя свойства в коде не совпадает с именем аутлета в Interface Builder.

  4. Элемент UI удален из storyboard, но ссылка в коде осталась.

  5. Попытка доступа до загрузки view. Аутлеты инициализируются в момент загрузки view (loadView() / viewDidLoad). Обращение к ним раньше (например, в init) вернет nil.

    override func viewDidLoad() {
        // ОШИБКА: myLabel еще nil, т.к. super.viewDidLoad() не вызван
        // myLabel.text = "Hello"
    
        super.viewDidLoad() // Здесь загружаются аутлеты
    
        // ПРАВИЛЬНО: Теперь myLabel загружен
        myLabel.text = "Hello"
    }
  6. Использование strong вместо weak ссылки (редко, но может мешать освобождению памяти).

Решение: Проверить связи в Interface Builder (правая панель, раздел "Connections Inspector") и убедиться, что view контроллера загружена.