0

I want to have a root NavigationStack that lets the user navigate around a SwiftUI app, including to a TabView with tabs that have their own navigation stack. Unfortunately, this seems to not work at all (xcode 14.2, iOS 16).

The following example demonstrates the issue. When you attempt to navigate inside the tab view navigation stack, the tabs disappear and then the app goes into a broken state where navigation basically stops working entirely.

import SwiftUI

struct TabsView: View {
    var body: some View {
        TabView {
            NavigationStack {
                ZStack {
                    NavigationLink("Navigate to child tab", value: 1)
                }
                .navigationDestination(for: Int.self) { screen in
                    Text("Tab child \(screen)")
                }
            }
            .tabItem {
                Label("Screen 1", systemImage: "house")
            }
            
            Text("Screen 2")
                .tabItem {
                    Label("Screen 2", systemImage: "house")
                }
        }
    }
}

struct ContentView: View {
    var body: some View {
        NavigationStack {
            VStack {
                NavigationLink("Show Tabs", value: "tabs")
            }
            .navigationDestination(for: String.self) { screen in
                if screen == "tabs" {
                    TabsView()
                } else {
                    Text("?")
                }
            }
        }
    }
}

How can I make this work?

Greg Ennis
  • 14,917
  • 2
  • 69
  • 74
  • does this answer you question. [Swift navigation bar not appearing](https://stackoverflow.com/questions/74200623/swift-navigation-bar-not-appearing/74203230#74203230). – Qazi Ammar Dec 14 '22 at 06:03
  • 1
    Apple doesn’t want a TabView below a NavigstionView/Stack it must always be at the top [this answer](https://stackoverflow.com/questions/74162743/interacting-with-a-confirmationdialog-or-alert-is-causing-the-parent-view-to-pop/74163592#74163592) elaborates a little – lorem ipsum Dec 14 '22 at 07:57
  • But it works fine if I use the old NavigationView instead of the newer NavigationStack, so I don't think that's really the issue. – Greg Ennis Dec 14 '22 at 10:56
  • It just appears to look fine on iPhone the issues are clear if you try on iPad (Double column) and try to assign navigation title's, you end up having to hide navigation bars, etc. Apple has gone out of their way to enforce that they shouldn't be related. – lorem ipsum Dec 14 '22 at 12:50
  • @loremipsum ok thanks. But... so before the user logs in, I have to show them all the other tabs in the app even though they can't use it? That doesnt seem ideal. I want to navigate to the main tabs interface only after the user logs in. If Apple really wanted to prevent this, seems like they would just throw an exception right away instead of just letting weird bugs happen in apps. – Greg Ennis Dec 14 '22 at 12:52
  • No, you can work around since the difference is logging in, if logged in show navigation stack else show tab view. As long as the tabview isn't in the stack it will be ok – lorem ipsum Dec 14 '22 at 12:54
  • That's what I ended up doing but it's annoying. There is no reason why I shouldn't be able to do this. It works great in UIKit, so I'm still not convinced that Apple is just intentionally letting weird bugs prevent devs from doing this. – Greg Ennis Dec 14 '22 at 12:59
  • 1
    You can also create your own tab view and all the issues are gone, it only takes a few lines of code. – lorem ipsum Dec 14 '22 at 13:00

1 Answers1

0

Use NavigationView in ContentView. Apple has problems with NavigationStack in hierarchy of NavigationStack.

  • 1
    NavigationView has been deprecated and Apple specifically states to move away from it and use NavigationStack instead. https://developer.apple.com/documentation/swiftui/migrating-to-new-navigation-types – Greg Ennis Feb 10 '23 at 14:18