import SwiftUI import os extension Logger { fileprivate static let nav = Logger(subsystem: Bundle.main.bundleIdentifier ?? "unknown", category: "nav") } enum Selection: String, CaseIterable, Codable, Sendable { case first case second var opposite : Selection { switch self { case .first: .second case .second: .first } } } struct Path : Hashable, CustomStringConvertible { let string : String let value : Int var selection : Selection { Selection(rawValue: string) ?? .first } var description: String { "Path: \(string)-\(value)" } } @Observable final class Navigation: CustomStringConvertible { var selection : Selection? var firstPath : [Path] var secondPath : [Path] internal init(selection: Selection = .first, firstPath : [Path] = [], secondPath : [Path] = []) { self.selection = selection self.firstPath = firstPath self.secondPath = secondPath } func navigate(selection: Selection) { Logger.nav.log("nav to selection: \(selection.rawValue, privacy: .public)") self.selection = selection } func navigate(path: Path) { Logger.nav.log("nav to path: \(path, privacy: .public)") let pathSelection = path.selection if selection == pathSelection { Logger.nav.log("just path") self.path.append(path) } else { Logger.nav.log("selection: \(pathSelection.rawValue, privacy: .public) and path") self.selection = pathSelection // here is the bug? self.path = [path] } } var path : [Path] { get { guard let selection else { return [] } switch selection { case .first: return firstPath case .second: return secondPath } } set { guard let selection else { return } switch selection { case .first: firstPath = newValue case .second: secondPath = newValue } } } var description : String { let sv = selection?.rawValue ?? "nil" return "s: \(sv) fp: \(firstPath) sp: \(secondPath)" } } struct SelectionView : View { let navigation: Navigation let selection : Selection var body: some View { Text("Selection: \(selection.rawValue)") Text("\(navigation)") let link = Path(string:selection.opposite.rawValue, value: 1) NavigationLink("Nav Link: \(link)", value: link) let sel = selection.opposite Button("Nav Sel: \(sel.rawValue)") { navigation.navigate(selection: sel)} let path = Path(string: selection.opposite.rawValue, value: 100) Button("Nav Path: \(path)") { navigation.navigate(path: path)} } } struct DestinationView : View { let navigation: Navigation let path : Path var body: some View { Group { Text("Destination: \(path)") Text("\(navigation)") let link = Path(string:path.string, value: path.value + 1) NavigationLink("Nav Link: \(link)", value: link) let path = Path(string:path.string, value: path.value + 100) Button("Nav Path: \(path)") { navigation.navigate(path: path)} }.navigationTitle(Text("\(path)")) } } struct ContentView: View { @State private var navigation = Navigation() var body: some View { @Bindable var nav = navigation NavigationSplitView { List(Selection.allCases, id: \.self, selection: $nav.selection) { selection in Text(selection.rawValue) } .navigationTitle(Text("Root")) } detail: { if let selection = nav.selection { NavigationStack(path: $nav.path) { SelectionView(navigation: navigation, selection: selection) .navigationDestination(for: Path.self) { DestinationView(navigation: navigation, path: $0) } } .navigationTitle(Text(selection.rawValue)) } else { Text("Select Something") } } } }