I'm trying to make a three column Split View where the sidebar determines the type of content, so I was hoping to have separate views drive the Lists for each content type, but I'm getting an issue where the selections get out of sync / don't highlight. For simplicity, I tested using a sidebar/detail Split View, as follows:
struct StringItem : Identifiable, Hashable {
let id = UUID()
let item : String
}
struct SimpleSplitView: View {
@State private var selString : StringItem?
let content = [StringItem(item: "Here"), StringItem(item: "There"), StringItem(item: "Everywhere") ]
var body: some View {
NavigationSplitView {
// This
List(content, selection: $selString) { c in
NavigationLink(value: c) {
Text(c.item)
}
}
// or this
ContentStringX(selection: $selString)
} detail: {
if let s = selString {
DetailStringX(item: s)
} else {
Text("Empty")
}
}
}
}
struct ContentStringX: View {
let content = [StringItem(item: "Here"), StringItem(item: "There"), StringItem(item: "Everywhere") ]
@Binding var selection : StringItem?
var body: some View {
List(content, selection: $selection) { c in
NavigationLink(value: c) {
Text(c.item)
}
}
}
}
struct DetailStringX: View {
var item : StringItem
var body: some View {
VStack{
Spacer()
Text("Detail String " + item.item)
Spacer()
}
}
}
Ignore for a moment that my sidebar has two sections, the behavior is the same whether "This" or "or this" are used alone. You can see the highlighted selection of "There" from the upper sidebar selection and the corresponding detail. If I select any of the items in the lower sidebar part (from the embedded child view ContentStringX
the detail is properly passed, but the selection isn't highlighted. Is it ok to pass the binding from the parent to the child to the list?
Second curiosity, is if I had a simpler content array of just Strings and used id:.self, then the selection works from within the nested child (other problems happen with uniqueness).
Hi,
Try making your content variables be @State private var content
instead.
This code updated correctly for me
struct ContentView: View {
@State private var selString : StringItem?
@State private var content = [StringItem(item: "Here"), StringItem(item: "There"), StringItem(item: "Everywhere") ]
var body: some View {
NavigationSplitView {
// This
List(content, selection: $selString) { c in
NavigationLink(value: c) {
Text(c.item)
}
}
// or this
ContentStringX( selection: $selString)
} detail: {
if let s = selString {
DetailStringX(item: s)
} else {
Text("Empty")
}
}
}
}
struct ContentStringX: View {
@State private var content : [StringItem] = [StringItem(item: "Here2"), StringItem(item: "There2"), StringItem(item: "Everywhere2") ]
@Binding var selection : StringItem?
var body: some View {
List(content, selection: $selection) { c in
NavigationLink(value: c) {
Text(c.item)
}
}
}
}
struct DetailStringX: View {
var item : StringItem
var body: some View {
VStack{
Spacer()
Text("Detail String " + item.item)
Spacer()
}
}
}