4

I'm trying to use NavigationStack inside NavigationSplitView.

struct ContentView: View {
    @State var mainMenu: MenuItem?
    @State var subMenu: SubMenuItem?
    
    var body: some View {
        NavigationSplitView {
            List(MenuItem.allCases, selection: $mainMenu) { item in
                NavigationLink(value: item) {
                    Text(item.rawValue)
                }
            }
        } detail: {
            NavigationStack {
                List(SubMenuItem.allCases, selection: $subMenu) { item in
                    NavigationLink(value: item) {
                        Text(item.rawValue)
                    }
                }
                .navigationDestination(for: SubMenuItem.self) { selected in
                    DetailView(item: selected)
                }
            }
        }
    }
}
struct DetailView: View {
    let item: SubMenuItem
    
    var body: some View {
        Text(item.id)
    }
}

On the Mac, I'm able to navigate well into the DetailView

enter image description here

But on iPhone and iPad, I'm unable to navigate to DetailView. I'm stuck on SubMenu.

enter image description here

enter image description here

Is this a known bug? or is there something wrong with my code?

P.S. I found this question almost similar to this, but I'm NOT using multiple/nested .navigationDestination and my problem occurs on iPhone/iPad, not on Mac.

1 Answer 1

8

Finally figured it out. I used the NavigationStack with path, and manually set the path for every subMenu change. Now the code works on every platform.

struct ContentView: View {
    @State var mainMenu: MenuItem?
    @State var subMenu: SubMenuItem?
    @State var path: [SubMenuItem] = []
    
    var body: some View {
        NavigationSplitView {
            List(MenuItem.allCases, selection: $mainMenu) { item in
                NavigationLink(value: item) {
                    Text(item.rawValue)
                }
            }
            .onChange(of: mainMenu) { _ in
                // Reset subMenu selection (optional)
                subMenu = nil
            }
        } detail: {
            NavigationStack(path: $path) {
                List(SubMenuItem.allCases, selection: $subMenu) { item in
                    NavigationLink(value: item) {
                        Text(item.rawValue)
                    }
                }
                .navigationDestination(for: SubMenuItem.self) { selected in
                    DetailView(item: selected)
                }
                .onChange(of: subMenu) { sm in
                    // Manually set the path
                    if let sm {
                        path = [sm]
                    }
                }
            }
        }
    }
}
2
  • 3
    This works, however, where I embed a NavigationStack inside a NavigationSplitView, I get the following message in the console Update NavigationRequestObserver tried to update multiple times per frame. BTW this is on Xcode 14.2.
    – Nitesh
    Dec 27, 2022 at 14:57
  • I am getting the same "Update NavigationRequestObserver tried to update multiple times per frame" when using this approach. Did you find a fix for this or the proper way to do this?
    – alionthego
    May 26, 2023 at 2:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.