Базовые вью и модификаторы

Вью — это кирпичики интерфейса, а модификаторы — способ настроить их внешний вид и поведение. Из них собирается любой экран.
Суть урока: каждый модификатор возвращает новое вью, оборачивая предыдущее. Поэтому порядок модификаторов важен: padding до и после фона дают разный результат.

Самые частые вью — Text (текст), Image (картинка) и Button (кнопка). Их настраивают модификаторами — методами, начинающимися с точки, которые меняют вид или поведение:

Text("Привет, SwiftUI")
    .font(.title)
    .foregroundStyle(.blue)
    .padding()
    .background(.yellow)

Читается сверху вниз как конвейер: взять текст, задать шрифт, перекрасить, добавить отступ, залить фоном. Ключевая тонкость — порядок модификаторов. Каждый из них оборачивает результат предыдущего, поэтому смена порядка меняет картинку:

// Отступ ВНУТРИ жёлтого фона
Text("A").padding().background(.yellow)

// Жёлтый фон БЕЗ отступа, отступ снаружи
Text("A").background(.yellow).padding()

Кнопка принимает действие (замыкание) и метку:

Button {
    print("Нажато")
} label: {
    Text("Купить")
        .padding()
        .background(.green, in: .capsule)
        .foregroundStyle(.white)
}

Картинки из системного набора SF Symbols подключаются по имени:

Image(systemName: "star.fill")
    .font(.largeTitle)
    .foregroundStyle(.yellow)
Text("A")
   .padding()        ->  [  A  ]   (отступ вокруг буквы)
   .background(.y)   ->  [[ A ]]   (фон оборачивает уже с отступом)

  vs

Text("A")
   .background(.y)   ->  [A]       (фон вплотную)
   .padding()        ->   [A]      (отступ снаружи фона)

Попробуй сам ▶ — запусти код прямо в браузере (Pyodide). Здесь нет Swift, но логика та же, что под капотом мобильного кода:

# Моделируем цепочку модификаторов как последовательность обёрток.
def apply(view, mod):
    return f'{mod}({view})'

# Порядок 1: сначала padding, потом background
v1 = 'Text'
v1 = apply(v1, 'padding')
v1 = apply(v1, 'background')
print('Вариант 1:', v1)

# Порядок 2: меняем местами — другой результат
v2 = 'Text'
v2 = apply(v2, 'background')
v2 = apply(v2, 'padding')
print('Вариант 2:', v2)
# Видно: каждая обёртка меняет смысл следующей.

Как работает под капотом

Модификатор — это не настройка существующего объекта, а функция, возвращающая новое вью, которое оборачивает исходное. Text("A").padding() на самом деле создаёт обёртку ModifiedContent вокруг текста. Поэтому цепочка модификаторов — это вложенные структуры, и порядок определяет, кто кого оборачивает. Понимание этой вложенности объясняет, почему padding и background не коммутируют.

Частые ошибки

  • Ожидать, что порядок модификаторов не важен. Он важен почти всегда.
  • Перегружать одно вью десятком модификаторов. Иногда чище вынести стиль в отдельный модификатор или вью.
  • Путать foregroundStyle и background. Первый красит содержимое, второй — фон.

Best practices

  • Помните мнемонику: модификаторы применяются изнутри наружу.
  • Используйте SF Symbols для иконок — они масштабируются и подстраиваются под шрифт.
  • Выносите повторяющиеся стили в собственные модификаторы для единообразия.

Итоги. Text, Image и Button — базовые вью, а модификаторы настраивают их, оборачивая один в другой. Порядок модификаторов критичен. Освоив эту механику, вы сможете собрать любой визуальный элемент.

Шире контекста

За кажущейся простотой модификаторов скрывается элегантная композиционная модель. Поскольку каждый модификатор возвращает новое вью, оборачивающее предыдущее, вы фактически строите дерево обёрток, и порядок в этом дереве определяет визуальный результат. Эта же идея позволяет создавать собственные переиспользуемые модификаторы: если в приложении десять кнопок выглядят одинаково, вы описываете стиль один раз и применяете его везде, гарантируя единообразие и упрощая будущие правки. SF Symbols — отдельный подарок от Apple: тысячи векторных иконок, которые масштабируются вместе со шрифтом, поддерживают разные начертания и цвета, автоматически адаптируются к тёмной теме. Привыкайте мыслить интерфейс как набор маленьких настраиваемых вью, собираемых в композицию: это не только делает код чище, но и раскрывает всю мощь декларативного подхода, где сложное всегда собирается из простого предсказуемым образом.

Проверьте себя
1. Что делает каждый модификатор вью в SwiftUI?
AМеняет исходное вью на месте
BВозвращает новое вью, оборачивающее предыдущее
CУдаляет предыдущие модификаторы
DНичего не возвращает
2. Почему .padding().background() и .background().padding() дают разный результат?
AЭто баг SwiftUI
BПотому что каждый модификатор оборачивает результат предыдущего
CBackground всегда игнорирует padding
DPadding работает только с текстом