Search code examples
swiftswiftuiswift5navigationviewtabview

NavigationView inside a TabView Swift UI


I'm just picking up SwiftUI after a long break but I don't understand why I can't place a Navigation View within a Tab View.

I want my Navigation View to be a .tabItem so the view appears as part of the main app navigation so I'm trying this :

struct ContentView: View {
    var body: some View {
            TabView {
            
        NavigationView {
            
            .tabItem {
                Text("Home")
            }
                    
            Text("Tab bar test")
                .navigationBarTitle("Page One")
        }
}

This doesn't work with error message

Cannot infer contextual base in reference to member 'tabItem'

But when I try this

    var body: some View {
        TabView {
        
    NavigationView {
                
        Text("Tab bar test")
            .navigationBarTitle("Page One")
    }
}
    .tabItem {
        Image(systemName: "1.circle")
        Text("Home")
    }
}

It builds fine but the tab bar doesn't show up.

My primary question which I'm hoping would be useful to others, is ...

Why can't I make a make a Navigation View a tab bar item by nesting .tabItem directly inside the Navigation View (as per my first example)?

I think it's a similar question to this one but there's no code there. And then quite similar to this one but they seem to be using .tabItem directy with ContentView like I want to with NavigationView but that isn't building!?

I'm probably misunderstanding something simple but I don't get this at all at the moment.


Solution

  • .tabItem should be used as a modifier on the view that represents that tab.

    In the first example, this doesn't work because of a syntax error -- you're trying to use it on the opening of a closure in NavigationView {, when instead you want it on the outside of the closing brace: NavigationView { }.tabItem(...)

    In the second example, you're using .tabItem as a modifier on the entire TabView instead of the NavigationView.

    Both of your examples may have revealed what was going on more obviously if you indent your code so that you can see the hierarchy. Trying selecting your code in Xcode and using Ctrl-I to get Xcode to properly format it for you.

    Here's a working version:

    struct ContentView : View {
        var body: some View {
            TabView {
                NavigationView {
                    Text("Tab bar test")
                        .navigationBarTitle("Page One")
                }
                .tabItem { //note how this is modifying `NavigationView`
                    Image(systemName: "1.circle")
                    Text("Home")
                }
                
            }
        }
    }