Search code examples
iosswiftiphoneswiftuiswiftui-navigationview

NavigationViews with TabView and Signed in / Signed out state swiftui


Here is the general structure of my code right now. Basically I am trying to make an app where a user has to sign in to use. Once the user is signed in, they will be taken to a tab view. Right now I am experiencing some issues where sometimes I will get double navbar/toolbars at the top of my screens. I'm worried that my current set up of NavigationViews is causing issues.

@main
struct MyApp: App {
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ContentView: View {
    var isSignedIn: Bool
    
    var body: some View {
        NavigationView {
            if isSignedIn {
                MainTabView()
            } else {
                WelcomeScreenView()
            }
        }
    }
}

struct WelcomeScreenView: View {
    
    var body: some View {
        ZStack {
            VStack {
                NavigationLink(destination: SignUpView(),
                               label: {
                    PrimaryButton(title: "Sign Up")
                })
            }
        }
    }
}

struct MainTabView: View {
    
    var body: some View {
        TabView {
            
            HomeView()
                .tabItem {
                    Image(systemName: "house.fill")
                    Text("Home")
                }
            
            SearchView()
                .tabItem {
                    Image(systemName: "magnifyingglass")
                    Text("Search")
                }
                .navigationViewStyle(.stack)
            
            ProfileView()
                .tabItem {
                    Image(systemName: "person.fill")
                    Text("Profile")
                }
                .tag(Tab.profile)
        }
    }
}

struct HomeView: View {
    
    var body: some View {
        NavigationView {
            ZStack {
                VStack {
                    Text("Home")
                }
            }
        }
    }
}

struct SearchView: View {
    
    var body: some View {
        NavigationView {
            ZStack {
                VStack {
                    Text("Search")
                }
            }
        }
    }
}

struct ProfileView: View {
    
    var body: some View {
        NavigationView {
            ZStack {
                VStack {
                    Text("Profile")
                }
            }
        }
    }
}

I have tried moving around the NavigationViews but that seems to only cause more issues.


Solution

  • The TabView must always be at the top it cannot be inside another navigation structure.

    https://developer.apple.com/design/human-interface-guidelines/tab-bars

    You can change your code to something like

    struct ContentView: View {
        var isSignedIn: Bool
        
        var body: some View {
            
            if isSignedIn {
                MainTabView()
            } else {
                NavigationView {
                    WelcomeScreenView()
                }
            }
        }
    }
    

    Also note that NavigationView was deprecated in iOS 16 NavigationStack is a much better option.

    https://developer.apple.com/documentation/swiftui/migrating-to-new-navigation-types