In this episode, you learn how to create a tabbed application using TabView and the tabItem modifier. The setup is much simpler than using UIKit's UITabBarController class. Decorating the tab bar items with an icon and a title couldn't be simpler. Let's fire up Xcode and create a project.

Creating the Project

We choose the App template from the iOS > Application section. Give your project a name and make sure Interface is set to SwiftUI. Tell Xcode where you would like to save the files for the project and hit Create.

Creating a Tabbed Application in SwiftUI

Creating a Tabbed Application in SwiftUI

Creating Views

A tabbed application displays two or more views so the first task is creating a few views the tabbed application can display. We create a SwiftUI view with name LeftView and a SwiftUI view with name RightView. We keep the implementation simple. Each view simply displays a title at its center.

struct LeftView: View {
    var body: some View {
        Text("Left View")
            .font(.title)
    }
}
struct RightView: View {
    var body: some View {
        Text("Right View")
            .font(.title)
    }
}

Creating the Tab View

To turn the application in a tabbed application, we make use of the TabView struct. Open ContentView.swift and remove the contents of the computed body property. The idea is for the ContentView struct to host the tab view.

struct ContentView: View {
    var body: some View {

    }
}

Add a TabView object to the computed body property. The initializer accepts a closure, the content of the tab view. In the closure, we create a LeftView object and a RightView object. These views are the child views, that is, the tabs of the tab view.

struct ContentView: View {
    var body: some View {
        TabView {
            LeftView()
            RightView()
        }
    }
}

The preview shows that the tab view displays the left view, but there is no way for the user to switch to the other child view, the right view. This is easy to fix. We apply the tabItem modifier to each of the child views. As the name suggests, the tabItem modifier defines the user interface of the tab bar item of the view it is applied to.

The initializer takes a closure as its only argument. The view we return from the closure is the tab bar item of the child view. In this example, we return a Label object that displays a title and an icon.

struct ContentView: View {
    var body: some View {
        TabView {
            LeftView()
                .tabItem {
                    Label("Left", systemImage: "return.left")
                }
            RightView()
        }
    }
}

We also apply the tabItem modifier to the right view, return a Label object from the closure we pass to the tabItem modifier.

struct ContentView: View {
    var body: some View {
        TabView {
            LeftView()
                .tabItem {
                    Label("Left", systemImage: "return.left")
                }
            RightView()
                .tabItem {
                    Label("Right", systemImage: "return.right")
                }
        }
    }
}

The tabbed application displays two tab bar items at the bottom. The selected tab bar item has a blue highlight. Tapping the unselected tab bar item takes the user to the corresponding child view.

Creating a Tabbed Application in SwiftUI

Decorating Tab Bar Items

We can tweak the user interface of the tabbed application with a few view modifiers. If we only want the tab bar item to display the title, we set the style of the label to titleOnly using the labelStyle modifier. The available label styles are automatic, titleAndIcon, iconOnly, and titleOnly.

struct ContentView: View {
    var body: some View {
        TabView {
            LeftView()
                .tabItem {
                    Label("Left", systemImage: "return.left")
                        .labelStyle(.titleOnly)
                }
            RightView()
                .tabItem {
                    Label("Right", systemImage: "return.right")
                        .labelStyle(.iconOnly)
                }
        }
    }
}

Creating a Tabbed Application in SwiftUI

Like a UIKit tab bar item, you can overlay a tab bar item with a badge using the badge modifier. Note that the badge modifier is applied to the child view.

struct ContentView: View {
    var body: some View {
        TabView {
            LeftView()
                .tabItem {
                    Label("Left", systemImage: "return.left")
                }
                .badge(4)
            RightView()
                .tabItem {
                    Label("Right", systemImage: "return.right")
                }
                .badge("NEW")
        }
    }
}

The badge of the left view tab bar item displays an integer whereas the badge of the right view tab bar item displays a string.

Creating a Tabbed Application in SwiftUI

What's Next?

Creating a tabbed application is much simpler using SwiftUI than it is using UIKit's UITabBarController class. The TabView struct makes displaying one or more child views a breeze and the tabItem modifier allow you to customize the tab bar item of each child view.