I am using the master-detail-concept in the content/detail area of a SwiftUI NavigationSplitView. Everything works perfectly if the selected item stays part of the list (the master). Changing the selection updates the detail view as expected:
But: If the selected item disappears from the list (or in extrem, the list becomes empty; might happen as a result of a change in some remote system), the list itself updates fine (removes the item/becomes empty/is not created), but the selection (binding) is not reseted and the detail view is not updated.
I created a small example view to show the problem with simple code. None of the versions from A to C do work.
struct ExampleView: View {
@State private var splitViewVisibility: NavigationSplitViewVisibility = .all
@State private var listEnabled = true
@State private var selectedItem: String? = nil
private let items = ["A", "B", "C", "D"]
var body: some View {
NavigationSplitView(columnVisibility: $splitViewVisibility) {
Toggle("List", isOn: $listEnabled)
}
content: {
// Version A
List(selection: $selectedItem) {
ForEach(listEnabled ? items : [], id: \.self) { item in
Text(item)
}
}
// Version B
/*
List(listEnabled ? items : [], id: \.self, selection: $selectedItem) { item in
Text(item)
}*/
// Verson C
/*
if listEnabled {
List(items, id: \.self, selection: $selectedItem) { item in
Text(item)
}
}*/
}
detail: {
Text("\(selectedItem ?? "No selection")")
}
}
}
What is needed to make the master-detail-concept work as expected: Reset the selection when the selected item disappears or the list becomes empty and then update the detail accordingly.
BTW: I already tried a '.onChange(of: items)' solution, but as the real data might be a very large bulk of hierarchical information, a search for the (old) selected object in the new data would be very time consuming.