2

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

Fawkes
  • 3,831
  • 3
  • 22
  • 37

1 Answers1

1

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

Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
  • Tnx! Any hints about how to hide the navigation bar including the back button? It seems like it ignores the .navigationBarHidden no matter where I put it. – Fawkes Feb 20 '23 at 17:41
  • Please ask that as another question to make sure people see it – Ashley Mills Feb 20 '23 at 17:46
  • Unfortunately really running out of time atm. If you want, you can create this question. The solution is to set .navigationBarHidden(true) on the views inside the `.navigationDestination` closure. Also as of iOS 16 it is now recommended to use `.toolbar(.hidden)` instead. – Fawkes Feb 20 '23 at 17:49