Section в SwiftUI — контейнерный компонент для логической группировки элементов внутри Form или List. Компонент отображает содержимое как визуальный блок с системными отступами, закруглёнными углами и опциональными заголовком и футером. По данным Apple Developer Documentation (2025), Section не управляет данными, а только организует представление: все дочерние элементы наследуют её стиль и отступы, обеспечивая структурированное отображение форм и списков.
Главное
Section — это структурный компонент SwiftUI, предназначенный для группировки элементов внутри контейнеров Form и List. В отличие от VStack или HStack, Section добавляет системные отступы, заголовок и футер, а также визуальное выделение группы в виде блока с закруглёнными углами на iOS.
Section не изменяет поведение дочерних элементов — она только организует их представление. Все контролы внутри Section — Picker, Toggle, TextField — работают как обычно, но визуально объединены в логическую группу. Это особенно важно для экранных форм, где пользователь должен быстро ориентироваться в структуре вводимых данных.
Система автоматически управляет отступами между секциями: расстояние между Section на iOS составляет 16–20 пунктов, между элементами внутри Section — 0 (разделитель между строками). Разработчик не может изменить эти отступы через модификаторы padding — они контролируются системой для обеспечения единообразного внешнего вида.
Section принимает два опциональных параметра: header — заголовок группы, и footer — поясняющий текст под группой. Заголовок отображается над элементами секции полужирным шрифтом caption-стиля, футер — меньшим шрифтом с серым цветом. Оба параметра принимают любую SwiftUI View, не только Text.
Заголовок Section помогает пользователю понять, к какой категории относятся элементы внутри группы. Например, на экране настроек заголовки «Уведомления», «Приватность» и «Аккаунт» мгновенно ориентируют пользователя. Футер уместен для пояснений: «Отключите уведомления на время встречи» или «Пароль должен содержать не менее 8 символов». Футер автоматически переносится на несколько строк при необходимости.
Section(
header: Text("Account Security"),
footer: Text("Use a strong password with at least 8 characters.")
) {
SecureField("Current password", text: $currentPassword)
SecureField("New password", text: $newPassword)
}
В примере Section имеет заголовок «Account Security» и футер с советом по безопасности пароля. Пользователь видит заголовок как метку раздела, заполняет два поля и сразу читает предупреждение под ними. Такая структура улучшает UX, так как вся информация о разделе находится на одном экране без необходимости переходить к отдельной справке.
Section работает как внутри Form, так и внутри List, но визуальное представление различается. В Form Section отображается как блок с закруглёнными углами и системным фоном, отделённый от соседних секций отступами. В List Section может использовать стиль plain — без фона и закруглений, или inset-grouped — с закруглёнными блоками, аналогично Form.
Выбор контейнера влияет на стиль Section. Если разместить Section с одинаковым содержимым внутри Form и List со стилем .insetGrouped, результат будет идентичным. Однако Form добавляет системные отступы и по умолчанию использует grouped-стиль, тогда как List требует явного указания стиля через модификатор .listStyle(.insetGrouped).
| Контейнер | Section по умолчанию | Доступные стили |
|---|---|---|
| Form | InsetGrouped с закруглёнными углами | .grouped (только Form) |
| List | Plain — без фона секции | .plain, .inset, .insetGrouped, .sidebar |
Для достижения одинакового внешнего вида в List используйте .listStyle(.insetGrouped). Этот стиль имитирует внешний вид Form и подходит для экранов настроек, построенных на List. Для стандартных списков данных используйте .plain — без выделения секций, с тонкими разделителями между строками.
Section может содержать динамическое количество элементов через ForEach. Это позволяет создавать группы с повторяющимися элементами, сохраняя заголовок и футер для всей группы. ForEach внутри Section итерирует коллекцию данных и создаёт дочерние View для каждого элемента, не нарушая структуру секции.
Динамические секции полезны для экранов настроек с переменным количеством опций: список языков, доступных для выбора, перечень подключённых устройств или список push-подписок. Заголовок секции остаётся статическим, а содержимое меняется в зависимости от данных.
struct DynamicSectionView: View {
let categories = ["Work", "Personal", "Finance", "Health"]
@State private var selected = Set<String>()
var body: some View {
Form {
Section(header: Text("Categories"),
footer: Text("Select your preferred categories")) {
ForEach(categories, id: \.self) { category in
Toggle(category, isOn: Binding(
get: { selected.contains(category) },
set: { if $0 { selected.insert(category) }
else { selected.remove(category) } }
))
}
}
Section {
Text("Selected: \(selected.count) categories")
.foregroundStyle(.secondary)
}
}
}
}
В этом примере ForEach генерирует Toggle для каждой категории из массива categories. Заголовок и футер секции заданы один раз и применяются ко всей группе. Вторая секция отображает количество выбранных категорий — она не зависит от ForEach и остаётся статической. Такой подход позволяет создавать гибкие формы, где заголовок и футер контекстуализируют группу динамических элементов.
Рассмотрим полноценный пример экрана профиля с использованием Section для группировки данных. Форма содержит три секции: информация о пользователе, настройки приватности и статистика. Каждая секция использует свой заголовок, а последняя — футер с итоговой информацией.
struct ProfileView: View {
@State private var displayName = "Alex Johnson"
@State private var bio = "iOS developer"
@State private var isProfilePublic = true
@State private var showEmail = false
var body: some View {
Form {
Section(header: Text("Profile Info")) {
TextField("Display name", text: $displayName)
TextField("Bio", text: $bio, axis: .vertical)
.lineLimit(3)
}
Section(header: Text("Privacy")) {
Toggle("Public profile", isOn: $isProfilePublic)
Toggle("Show email", isOn: $showEmail)
.disabled(!isProfilePublic)
}
Section(header: Text("Stats"),
footer: Text("Last updated today at 2:30 PM")) {
LabeledContent("Posts", value: "42")
LabeledContent("Followers", value: "1,280")
LabeledContent("Following", value: "346")
}
}
.navigationTitle("Profile")
}
}
Три Section чётко разделяют функциональные блоки: редактируемые поля профиля, переключатели приватности и статистику. Вторая секция демонстрирует валидацию: Toggle «Show email» отключён, пока профиль не публичный. Футер третьей секции показывает время последнего обновления — пример использования футера для дополнительной контекстной информации. LabeledContent — стандартный компонент SwiftUI для отображения пары «ключ-значение» в Form.
Section(
header: HStack {
Image(systemName: "bell.fill")
.foregroundStyle(.blue)
Text("Notifications")
.font(.headline)
},
footer: Text("Manage push and email alerts")
) {
Toggle("Push notifications", isOn: $push)
Toggle("Email notifications", isOn: $email)
Stepper("Quiet hours: \(quietStart) — \(quietEnd)",
value: $quietStart,
in: 0...23)
}
Этот пример показывает, что header может быть любой SwiftUI View. Использование HStack с Image и Text позволяет добавить иконку рядом с заголовком, делая секцию визуально более выразительной. Кастомные заголовки полезны для выделения важных разделов в интерфейсе: настройки уведомлений, платные функции или разделы с предупреждениями. Однако злоупотреблять кастомными заголовками не стоит — на каждом экране достаточно 1–2 секций с нестандартным оформлением, чтобы сохранить единообразие интерфейса.
Часто задаваемые вопросы
Нет, Section не поддерживает вложенность в SwiftUI. Попытка поместить Section внутрь другой Section приводит к ошибке компиляции. Для иерархической группировки используйте List с OutlineGroup или DisclosureGroup внутри Section.
Отступы между Section управляются системой и не могут быть изменены через модификаторы padding. На iOS расстояние между секциями составляет 16–20 пунктов и соответствует HIG. Единственный способ повлиять на отступы — использовать кастомный ListStyle, но это не рекомендуется.
Group — невидимый контейнер для группировки элементов без визуального оформления. Section добавляет заголовок, футер, отступы и визуальный блок. Group используется для условного рендеринга, Section — для структурирования интерфейса.
Да, Section автоматически добавляет accessibility-метки. Заголовок секции становится accessibility-заголовком группы, футер — accessibility-подсказкой. VoiceOver читает заголовок перед входом в секцию, что улучшает навигацию для пользователей с ограниченными возможностями.
Нет, Section работает только внутри Form или List. Использование Section вне этих контейнеров приводит к ошибке компиляции. Для группировки элементов в VStack или ScrollView используйте Group или кастомные View с настройкой отступов вручную.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также