TabView builds both tab bars and swipeable pagers from the same container. Since WWDC20 it
works on iOS, macOS, watchOS, and tvOS, and one style modifier flips it from tabs to pages.
Basic Tabs
Wrap the children in a TabView and decorate each with tabItem. Only Image and Text
views work inside the tabItem closure; anything else is ignored.
TabView {
Text("Hello")
.tabItem {
Image(systemName: "heart.fill")
Text("Tab1")
}
Text("World")
.tabItem { Text("Tab2") }
}
Programmatic Selection
Deep links and notifications need to switch the tab in code. Pass a selection binding and tag each child; SwiftUI matches the binding value against the tags.
@State private var selection = 0
TabView(selection: $selection) {
Text("Hello")
.tabItem { Text("Tab1") }
.tag(0)
Text("World")
.tabItem { Text("Tab2") }
.tag(1)
}
Set selection from anywhere to switch tabs. Without a tag, the binding has nothing to
match and the switch does not happen.
Pager Style
tabViewStyle(PageTabViewStyle()) turns the same container into a horizontally swipeable
pager. The indexDisplayMode parameter controls the page-indicator dots.
TabView {
Text("Hello")
Text("World")
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
The selection binding animates. Wrap the change in withAnimation to drive next and previous
buttons with a slide transition.
Button("next") {
withAnimation { selection = 1 }
}
Platform Notes
- On watchOS the page style gives the standard vertical-swipe paging experience.
- On macOS a
TabViewinside a settings scene adopts the native settings-toolbar styling. - On tvOS the tab bar adapts to the TV top-bar look automatically.