18 Jun, 2019
SwiftUI TabbedView in Xcode 11 Beta 2
TabbedView is now
TabView (see https://developer.apple.com/documentation/swiftui/tabview). So much changed in such little time. What a ride! Last Updated 24 September 2019
At the time of writing (Xcode 11 Beta 2) SwiftUI's support for the TabbedView component is limited. Last Updated 18 June 2019
SwiftUI's counterpart to
UITabBarController which is described in the public documentation as:
A view which allows for switching between multiple child views using interactable user interface elements.
TabbedView's setup is briefly showcased in the WWDC19 session 216 SwiftUI Essentials and on the Avocado Toast demo app, the basic usage is shown to be as follows.
In practice, this code doesn't work yet, and it has left many of us scratching our heads. A Tabbed View is after all one of the most common UI patterns in mobile app development. In this article I intend to do a quick tutorial over what is possible to do right now with
Setup some content
In the snippet bellow I have created 2 rather simple
View instances. Each one with a
Text element. This is the dummy content that we will be loading in our
TabbedView as child views.
Build up the TabbedView
With our dummy content in place, we can build our
Here's a line by line by line breakdown of the code:
Line 5 - We declare our
TabbedView component. Note that we don't pass a
selection parameter for simplicity.
Line 6 - We compose
Tab1Content() inside the body of our
Line 7 - For our
Tab1Content() to have a Tab button, we add a
tabItemLabel generic instance function.
Line 8 - We compose a
Text element by passing it as the parameter in the
tabItemLabel generic instance function.
Line 9 - We apply
tag() another generic instance function, passing
0 as the parameter. There isn't a whole lot of documentation on this modifier, but it seems to accomplish the purpose of identifying the content inside the
TabbedView as well as defining its order of selection. If we switch around the
1 values in the
tag() modifiers we see that the initial selection is changed.
Line 10 - 14 Repeat the same steps for
This is quite different from what is shown in the WWDC session. There are 2 main differences:
In the WWDC session, no
tag() modifier is used. Without it though,
TabbedView fails to respond to the taps on the tabs, as seen in this Stackoverflow question.
In the WWDC session
tabItemLabel appears to have a different signature where it is possible to specify an
Image as well as a
Text element to form the tab button. This seems to be inside a body delimited by curly brackets that is not possible to write today. The public documentation on
TabbedView only supports tab items of type Text, Image, or a LayoutView of Image and Text. Passing any other type of view will result in a visible, empty tab item.
But a search for
LayoutView finds no results. For the time being it seems that this functionality is limited and only allows a simple
Text to be added to the tabs.
Additionally, passing an
Image instance instead of a
Text instance, doesn't work yet either.
TabbedView on tvOS
SwiftUI's flexibility it is possible to use the code above on
tvOS. The layout shown above renders like this.
TabbedView renders with some important layout differences to accommodate the totally different experience provided by an Apple TV device. Under the hood,
TabbedView is still rendering as a
The rendering of the tab buttons is not ideal as the color of the selected text makes it impossible to distinguish from the background.
And there you have it, the minimum setup possible for
SwiftUI. I look forward to the next release in July where I hope to see a more complete implementation of
You can find a finalized sample project at https://github.com/piterwilson/MyTabbedView
Sources and Further reading
- Apple, WWDC session 216, SwiftUI essentials, https://developer.apple.com/videos/play/wwdc2019/216/
- Apple, TabbedView, Retrieved from: https://developer.apple.com/documentation/swiftui/tabbedview
- Apple, tabItemLabel, Retrieved from: https://developer.apple.com/documentation/swiftui/tabbedview/3276774-tabitemlabel