In my project I want to navigate to the detail View in a NavigationSplitView. This however does not work, nothing happens. When I change the selection to the ID property all of it works. I made a very simple example view that demonstrates this (real project is bigger)
This doesn't work
struct ContentView: View {
var notes = [
Annotation(title: "Note 1", details: "Some details here", completed: false),
Annotation(title: "Note 2", details: "Some details here too", completed: true),
Annotation(title: "Note 3", details: "Some details here also", completed: false)
]
@State private var selected: Annotation?
var body: some View {
NavigationSplitView(columnVisibility: .constant(.doubleColumn)) {
List (selection: $selected) {
ForEach(notes) { annotation in
Text(annotation.title)
}
}
} detail: {
VStack {
Text(selected?.title ?? "-")
Text(selected?.details ?? "-")
//Text(selected?.uuidString ?? "###")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct Annotation: Hashable, Identifiable {
var id: UUID = UUID()
var title: String
var details: String
var completed: Bool
}
This works
struct ContentView: View {
var notes = [
Annotation(title: "Note 1", details: "Some details here", completed: false),
Annotation(title: "Note 2", details: "Some details here too", completed: true),
Annotation(title: "Note 3", details: "Some details here also", completed: false)
]
@State private var selected: Annotation.ID?
var body: some View {
NavigationSplitView(columnVisibility: .constant(.doubleColumn)) {
List (selection: $selected) {
ForEach(notes) { annotation in
Text(annotation.title)
}
}
} detail: {
VStack {
//Text(selected?.title ?? "-")
//Text(selected?.details ?? "-")
Text(selected?.uuidString ?? "###")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct Annotation: Hashable, Identifiable {
var id: UUID = UUID()
var title: String
var details: String
var completed: Bool
}
Any help appreciated!
By default, the ForEach
puts a tag
on each item with the item's id
. So, the selection is updated with that id
. If you want the tag
to match the entire item, you have to use the tag
modifier to explicitly do that:
List (selection: $selected) {
ForEach(notes) { annotation in
Text(annotation.title)
.tag(annotation) // <-- Here
}
}
Note that this is potentially dangerous, as if your model had a property that changed when you were on the detail view, it would no longer stay selected, since the equality would be broken. So, it's probably best/safest to stick with the id
-based selection.