Как программно работать с Auto Layout constraints в UIKit?

«Как программно работать с Auto Layout constraints в UIKit?» — вопрос из категории UIKit, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Работа с Auto Layout программно осуществляется через класс NSLayoutConstraint и систему anchors (якорей), которая более читаема и безопасна.

Базовый пример создания и активации констрейнтов:

let subview = UIView()
subview.backgroundColor = .systemBlue
view.addSubview(subview)

// КРИТИЧЕСКИ ВАЖНЫЙ ШАГ
subview.translatesAutoresizingMaskIntoConstraints = false

// Создание констрейнтов через активацию массива
NSLayoutConstraint.activate([
    // Привязка к safe area с отступами
    subview.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16),
    subview.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16),

    // Фиксированная высота
    subview.heightAnchor.constraint(equalToConstant: 100),

    // Вертикальное позиционирование: центр по Y
    subview.centerYAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor)
])

Ключевые концепции и лучшие практики:

  1. translatesAutoresizingMaskIntoConstraints = false — всегда устанавливайте для view, которыми управляете через Auto Layout. Иначе система попытается преобразовать старые autoresizing masks в constraints, что приведет к конфликтам.
  2. Приоритет (priority) и отношение (multiplier):
    // Констрейнт с низким приоритетом и множителем
    let widthConstraint = subview.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.8)
    widthConstraint.priority = .defaultLow
    widthConstraint.isActive = true
  3. Динамическое изменение констрейнтов: Храните ссылку на констрейнт и изменяйте его свойство constant.

    // Объявление
    private var topConstraint: NSLayoutConstraint!
    
    // Инициализация
    topConstraint = subview.topAnchor.constraint(equalTo: view.topAnchor, constant: 20)
    topConstraint.isActive = true
    
    // Анимация изменения
    UIView.animate(withDuration: 0.3) {
        self.topConstraint.constant = 100
        self.view.layoutIfNeeded() // Принудительный перерасчет layout
    }
  4. UIStackView — предпочтительный способ для группировки view. Он сам управляет констрейнтами для своих arrangedSubviews.
  5. Отладка: При конфликтах (Unable to simultaneously satisfy constraints) используйте po UIView._autolayoutTrace() в консоли LLDB или устанавливайте идентификаторы для constraints (identifier property) для понятного логирования.