Search code examples
swiftuiswiftui-navigationstack

Why NavigationStack's navigationDestination is not called when part of VStack?


NavigationStack .navigationDestination() is not called if the navigation stack is a child of another container.

The navigation happens visually but it only pushes to the stack a view with the typical yellow warning icon in the middle. If I make the NavigationStack the parent view then it does call the .navigationDestination() and everything works as expected except it does not satisfy the UI requirements.

iOS version: 16.2

Why is that and how can it be fixed?

An approximation of my code.

var body: some View {
    VStack {
        MyCustomTopBarView()
        MyAlwaysOnScreenNavigationStepsProgressBar()
        NavigationStack($path) {
            contentView()
        }
        .navigationDestination(for: NavigationState.self) { navigationState in

            switch navigationState {
            case .screen1:
                Text("screen 1")
            }
        }
        .navigationBarHidden(true)
    }
}

enter image description here


Solution

  • You just need to add .navigationDestination to the top level view within the NavigationStack, e.g…

    enum NavigationState {
        case screen1
    }
    
    struct ContentView: View {
        
        @State private var path = NavigationPath()
        
        var body: some View {
            VStack {
                MyCustomTopBarView()
                MyAlwaysOnScreenNavigationStepsProgressBar()
                NavigationStack(path: $path) {
                    contentView()
                        .navigationDestination(for: NavigationState.self) { navigationState in
    
                            switch navigationState {
                            case .screen1:
                                Text("screen 1")
                            }
                        }
                        .navigationBarHidden(true)
                }
                Button("Show content") {
                    path.append(NavigationState.screen1)
                }
            }
        }
        
        func contentView() -> some View {
            Text("Content")
        }
    }
    
    struct MyCustomTopBarView: View {
        var body: some View {
            Rectangle().fill(.red)
                .frame(height: 40)
        }
    }
    
    struct MyAlwaysOnScreenNavigationStepsProgressBar: View {
        var body: some View {
            ProgressView()
                .progressViewStyle(.linear)
        }
    }
    

    enter image description here