Search code examples
iosswiftswiftuinavigationviewswiftui-tabview

Is there a good solution to use a TabView inside a NavigationView?


At first I know that for a good working environment the NavigationView should be inside the TabView, but the thing is I have to declare the NavigationView a few steps before you come to the TabBarView because first you have to complete a registration, which requires the NavigationView.

The problem is after the registration the NavigationBar in the TabView doesn't work. (Either the same NavigationBar is always displayed or none at all)

So for the beginning I will show you how my code looks right now:

This is the MyApp View where I declare the NavigationView:

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

Then we start with the StartView:

struct StartView: View {

   VStack{
      //View to Login
      NavigationLink(destination: LoginView(), label: {
          Text("Login View")
      })

      //View to Registration
      NavigationLink(destination: RegistrationView(), label: {
          Text("Registration View")
      })
   }
}

Then I start the registrationProcess where you go through different views to customise the app

On the last View of this process I have a NavigationLink to the MainView (The View with the TabBar) which is shown when the User is finish with his registration / logged in.

NavigationLink(destination: MainView(), label: { Text("To the Main View") })

And then this is the MainView, where the NavigationBars don't work as they should:

struct MainView: View {
    
    //Tab bar color
    init() {
        UITabBar.appearance().backgroundColor = UIColor.white
    }
    
    var body: some View {
        
        TabView(){
            
            //First
            FirstView()
                .tabItem{
                    Image(systemName: "person")
                }
            
            //Second
            SecondView()
                .tabItem{
                    Image(systemName: "person")
                }
            
            //Third
            ThirdView()
                .tabItem{
                    Image(systemName: "person")
                }
        }
    }
}

I browsed a lot now and didn't see anything, which would have helped me without remodelling my whole code. I hope someone can help me. Thanks


Solution

  • Thanks to @Paulw11's comment, I came across the following Youtube video and integrated the code it contains into my project: Change root view SwiftUI

    In my last View of the Registration Process I created a Button which navigated me to my MainView (TabView with NavigationLinks):

    Button(action: {
                    let window = UIApplication
                        .shared
                        .connectedScenes
                        .flatMap{ ($0 as? UIWindowScene)?.windows ?? [] }
                        .first { $0.isKeyWindow }
                    
                    window?.rootViewController = UIHostingController(rootView: MainView())
                    
                    window?.makeKeyAndVisible()
                    
                }, label: {
                    Text("To the Main View")
                })
    

    And then I changed my MainView to this:

    struct MainView: View {
        
        //Tab bar color
        init() {
            UITabBar.appearance().backgroundColor = UIColor.white
        }
        
        var body: some View {
            
            TabView(){
                
                //First
                NavigationView{ FirstView() }
                    .tabItem{
                        Image(systemName: "person")
                    }
                
                //Second
                NavigationView{ SecondView() }
                    .tabItem{
                        Image(systemName: "person")
                    }
                
                //Third
                NavigationView{ ThirdView() }
                    .tabItem{
                        Image(systemName: "person")
                    }
            }
        }
    }