📱
Адаптивные TabView с .tabViewStyle(.sidebarAdaptable) в SwiftUIРаньше
TabView на iPhone выглядела как нижний таб-бар, а на iPad хотелось чего-то более похожего на сайдбар: больше пространства, группировка пунктов, удобство на большом экране. Обычно приходилось строить кастомный сайдбар, разделять навигацию на отдельные структуры или писать условный код под каждую платформу.
.tabViewStyle(.sidebarAdaptable) меняет этот подход. Теперь
TabView может адаптироваться между таб-баром и сайдбаром, оставаясь в рамках стандартного SwiftUI API. Дополнительный модификатор
.defaultTabBarPlacement(.sidebar) даёт ещё один рычаг управления, позволяя предпочесть сайдбар для табов, когда используется адаптивный стиль.
🔹
Основная идеяAPI начинается с обычного
TabView:
struct RootView: View {
var body: some View {
TabView {
Tab("Home", systemImage: "house") {
HomeView()
}
Tab("Library", systemImage: "books.vertical") {
LibraryView()
}
Tab("Search", systemImage: "magnifyingglass") {
SearchView()
}
}
.tabViewStyle(.sidebarAdaptable)
}
}Вы не заменяете
TabView кастомным контейнером. Вы описываете места назначения один раз, а SwiftUI решает, как их представить: на iPhone это привычный таб-бар, на iPad — сайдбар.
🔹
Где применяется .defaultTabBarPlacement(.sidebar).sidebarAdaptable включает адаптивный стиль.
.defaultTabBarPlacement(.sidebar) сообщает SwiftUI, какое размещение предпочтительнее по умолчанию:
.tabViewStyle(.sidebarAdaptable)
.defaultTabBarPlacement(.sidebar)
Таким образом, когда
TabView может использовать адаптивный стиль, он начинает с сайдбара. Поведение всё ещё контролируется SwiftUI.
🧭
Важная деталь: NavigationStackКнопка сайдбара появляется в области навигации. Если таб содержит простое вью без навигационного контейнера, у SwiftUI может не быть видимой навигационной панели для размещения этого контрола.
Поэтому в реальном приложении каждый таб должен иметь собственный
NavigationStack и предоставлять
navigationTitle:
struct RootView: View {
var body: some View {
TabView {
Tab("Dashboard", systemImage: "speedometer") {
NavigationStack {
List {
Text("View Reports")
Text("Check Tasks")
Text("Team Activity")
}
.navigationTitle("Dashboard")
}
}
Tab("Messages", systemImage: "bubble.left.and.bubble.right") {
NavigationStack {
List(["Alice", "Bob", "Charlie"], id: \.self) { name in
NavigationLink {
Text("Chat with \(name)")
} label: {
Text(name)
}
}
.navigationTitle("Messages")
}
}
}
.tabViewStyle(.sidebarAdaptable)
.defaultTabBarPlacement(.sidebar)
}
}🔹 Почему это полезноНа iPad нижний таб-бар часто выглядит как паттерн с iPhone, перенесённый на большой экран. Сайдбар даёт больше места для меток, лучше группирует пункты и снимает ограничение "впихнуть всё в 4–5 табов".
Кроме того, у этой API есть ещё один интересный аспект.
Если Apple когда-нибудь выпустит складной iPhone, граница между iPhone и iPad перестанет быть чёткой. Закрытое устройство может вести себя как обычный iPhone, а развёрнутое — иметь пространство для сайдбара. Apple пока не анонсировала такое устройство, но направление этого API отлично вписывается в такое будущее.
Складной iPhone потребует приложений, которые могут переключаться между компактными и расширенными лейаутами без создания отдельной навигационной системы для каждого разработчика.
TabView с
.sidebarAdaptable — именно то API, которое в этом помогает.
Мне больше всего нравится в этом API то, что он не заставляет вас предугадывать каждую форму устройства.
🔹
Итог.tabViewStyle(.sidebarAdaptable) решает реальную проблему компоновки. Он позволяет SwiftUI использовать одну и ту же модель табов как в компактных, так и в расширенных интерфейсах.
.defaultTabBarPlacement(.sidebar) добавляет небольшое, но полезное предпочтение поверх этой модели.
Для iPad-приложений это уже имеет смысл. Для возможного складного iPhone это может стать ещё более важным.
📌
Лучшие вакансии для мобильных разработчиков🐸 Библиотека мобильного разработчика#PixelPerfect #Swift