0

The following code shows that $path is always 0, despite tapping a NavigationLink inside the stack. That means that when I select a panel, and tap on the navigation link to go to 'firstPanel subview', then select a new panel, it does not reset the NavigationStack's path.

If I use the new .navigationDestination API then it works, but I was under the impression that the older NavigationLink without value: should work too since it's not deprecated. This is on iOS 16.4.

Ideas:

  • I'm not binding to $path properly somehow
  • The NavigationStack doesn't understand its root view
  • I don't think I need a separate NavigationStack per panel?
  • Maybe I do need to use .navigationDestination everywhere? Perhaps it's intended that this NavigationLink doesn't modify the stack's path? Seems odd. I see older NavigationLinks in the FoodTruck sample app.
  • This may be unrelated to NavigationSplitView, just NavigationStack.

Screenshot showing firstPanel subview remaining after selecting secondPanel

import SwiftUI

enum Panel: String, Hashable {
    case firstPanel, secondPanel
}

struct ContentView: View {
    @State private var selection: Panel? = .firstPanel
    @State private var path = NavigationPath()
        
    var body: some View {
        NavigationSplitView {
            List(selection: $selection) {
                NavigationLink(value: Panel.firstPanel) {
                    Text(Panel.firstPanel.rawValue)
                }
                
                NavigationLink(value: Panel.secondPanel) {
                    Text(Panel.secondPanel.rawValue)
                }
            }
            .listStyle(.sidebar)
            .navigationTitle("MyApp")
        } detail: {
            NavigationStack(path: $path) {
                switch selection ?? .firstPanel {
                case .firstPanel:
                    NavigationLink {
                        Text("This is \(Panel.firstPanel.rawValue) subview") // <-- navigate to here, then tap secondPanel
                    } label: {
                        Text("Go to \(Panel.firstPanel.rawValue) subview")
                    }
                case .secondPanel:
                    NavigationLink {
                        Text("This is \(Panel.secondPanel.rawValue) subview")
                    } label: {
                        Text("Go to \(Panel.secondPanel.rawValue) subview")
                    }
                }
            }
        }
        .onChange(of: selection) { _ in
            print(path.count) // <-- always prints 0
            path.removeLast(path.count)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .previewDevice("iPad Pro (11-inch) (4th generation)")
            .previewInterfaceOrientation(.landscapeLeft)
    }
}

Thanks!

aspear
  • 78
  • 9
  • I have a similar issue where the path ends up being reset (without the use of a `NavigationLink` though): https://stackoverflow.com/questions/76338957/path-of-navigationstack-inside-navigationsplitview-emptied-on-change – Dominik May 26 '23 at 08:22
  • I'm thinking that because I'm not using `NavigationLink(value: )` it's not appending a value to the path, so the path remains empty. But it does successfully navigate somewhere with the older NavigationLink, so the stack state is being kept somewhere outside of the `path` I can access. Seems like others are confused as well; maybe Apple engineers need to make these work together better? Maybe the older NavigationLink should append some kind of value to `path` just so they work together better? I'm not sure. Still hoping for some clarification to this! – aspear May 27 '23 at 09:26

1 Answers1

0

In your code there is nothing that can be appended on path. SwiftUI needs some kind of data to actually append to path. NaviationLink examples on SwiftUI documents that doesn't use value to initialize are presented on navigationstack without path.

NavigationStack {
    List {
        NavigationLink("Mint") { ColorDetail(color: .mint) }
        NavigationLink("Pink") { ColorDetail(color: .pink) }
        NavigationLink("Teal") { ColorDetail(color: .teal) }
    }
    .navigationTitle("Colors")
}
andylee
  • 255
  • 2
  • 6