I'm glad to hear it's reproducing for you, and understand your theory about duplicate IDs. The actual app where this was originally detected uses UUIDs extensively, but it certainly doesn't hurt to use the same strategy in the reduced test case as well.
In the code below, not only are Item instances created with UUIDs rather than relying on string uniqueness, but every time the filter is invoked it generates new UUIDs for each item to ensure that there's not even overlap between the prior and new data sets. I still get the same crash. Table data is inherently ordered, so a Set is neither appropriate nor well-suited to SwiftUI's binding in this instance.
import SwiftUI
struct Item: Identifiable, Hashable {
let id = UUID()
let name: String
init(_ name: String) {
self.name = name
}
}
struct ContentView: View {
let allItems = [ Item("One"), Item("Two"), Item("Three"), Item("Four"), Item("Five"), Item("Six"), Item("Seven"), Item("Eight"), Item("Nine"), Item("Ten") ]
@State var filteredItems = [Item]()
@State var text: String = ""
func filter() {
let subset = if text == "" {
allItems
} else {
allItems.filter {
$0.name.localizedCaseInsensitiveContains(text)
}
}
// To guarantee that there are no duplicate IDs, generate new
// Item instances for the filtered set
filteredItems = subset.map { item in
Item(item.name)
}
}
var body: some View {
VStack {
TextField("Search:", text: $text)
.padding()
.onChange(of: text) {
filter()
}
.onAppear {
filter()
}
Table($filteredItems) {
TableColumn("Name") { item in
Text(item.wrappedValue.name)
}
}
}
}
}