Search code examples
iosswiftuiswiftui-navigationlinkswiftui-navigationsplitviewswiftui-navigationstack

SwiftUI NavigationStack inside NavigationSplitView not working on iPhone and iPad


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.


Solution

  • 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]
                        }
                    }
                }
            }
        }
    }