Skip to content

Instantly share code, notes, and snippets.

@chockenberry
Created April 17, 2024 17:43
Show Gist options
  • Save chockenberry/476ef4d8b1bfc73872dda8e0d9d8f49f to your computer and use it in GitHub Desktop.
Save chockenberry/476ef4d8b1bfc73872dda8e0d9d8f49f to your computer and use it in GitHub Desktop.
NavigationPath Experiments
//
// ContentView.swift
// NavigationTest
//
// Created by Craig Hockenberry on 4/16/24.
//
import SwiftUI
struct OddView: View {
@Binding var path: NavigationPath
//@Binding var path: [PathOptions]
var body: some View {
Form {
Section {
NavigationLink("Foo", value: "Foo Value")
NavigationLink("PIN", value: 1337)
NavigationLink("Pathless", value: PathOptions.pathless)
NavigationLink("First", value: PathOptions.first)
NavigationLink("Second", value: PathOptions.second)
NavigationLink("Third", value: PathOptions.third)
NavigationLink("Fourth", value: PathOptions.fourth)
NavigationLink("Fifth", value: PathOptions.fifth)
Button("Remove Last") {
path.removeLast()
}
Button("Back to Root") {
path.removeLast(path.count)
}
}
// NOTE: Disables selection completely. Not good.
//.listRowBackground(Color(UIColor.systemBackground))
}
.formStyle(.grouped)
.onAppear {
print("OddView: path.count = \(path.count)")
}
}
}
struct EvenView: View {
@Binding var path: NavigationPath
//@Binding var path: [PathOptions]
var body: some View {
Form {
Section {
NavigationLink("Bar", value: "Bar Value")
NavigationLink("PUNK", value: 999)
NavigationLink("Pathless", value: PathOptions.pathless)
NavigationLink("First", value: PathOptions.first)
NavigationLink("Second", value: PathOptions.second)
NavigationLink("Third", value: PathOptions.third)
NavigationLink("Fourth", value: PathOptions.fourth)
NavigationLink("Fifth", value: PathOptions.fifth)
Button("Remove Last") {
path.removeLast()
}
Button("Append First") {
path.append(PathOptions.first)
}
}
}
.formStyle(.grouped)
.onAppear {
print("EvenView: path.count = \(path.count)")
}
}
}
struct PathlessView: View {
var body: some View {
Form {
Section {
NavigationLink("First", value: PathOptions.first)
NavigationLink("Second", value: PathOptions.second)
NavigationLink("Pathless", value: PathOptions.pathless)
}
}
.formStyle(.grouped)
.onAppear {
print("PathlessView: no path binding")
}
}
}
enum PathOptions: String {
case first
case second
case third
case fourth
case fifth
case pathless
}
struct ContentView: View {
@State private var path = NavigationPath()
//@State private var path = [PathOptions.first, PathOptions.second]
var body: some View {
NavigationStack(path: $path) {
Form {
Section {
NavigationLink("First", value: PathOptions.first)
NavigationLink("Second", value: PathOptions.second)
}
}
.formStyle(.grouped)
.navigationTitle("ContentView")
.navigationDestination(for: PathOptions.self) { pathOption in
switch pathOption {
case .first:
OddView(path: $path)
.navigationTitle("First")
case .second:
EvenView(path: $path)
.navigationTitle("Second")
case .third:
OddView(path: $path)
.navigationTitle("Third")
case .fourth:
EvenView(path: $path)
.navigationTitle("Fourth")
case .fifth:
OddView(path: $path)
.navigationTitle("Fifth")
case .pathless:
PathlessView()
.navigationTitle("Pathless")
}
}
.navigationDestination(for: String.self) { string in
Text("View with '\(string)'")
.navigationTitle(string)
}
.navigationDestination(for: Int.self) { int in
Text("View with \(int)")
.navigationTitle("\(int)")
}
.onAppear {
print("ContentView: path = \(path.count)")
}
}
}
}
#Preview {
ContentView()
}
@chockenberry
Copy link
Author

The issue is that the row values for the NavigationLink are used to determine identity (they must be Hashable). When you have a cyclical graph, you need something else to make the row unique. One option is to add a "level" to the items you add to the NavigationPath:

https://gist.github.com/phillipcaudell/fda686d67bde2f87a9252fbd802fcc3a

This causes the hash value for the row to be unique, even if the underlying data is not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment