I want to create a sortable Table where each table cell is a TextField so that the cell contents can be edited.
Let's start with this unsortable Table that has only one column. In the real code, this is of course going to have more columns and rows can be added and removed too.
struct ContentView: View {
@State var rows = [
Row(name: "A"),
Row(name: "B"),
]
var body: some View {
Table($rows) {
TableColumn("Name") { $row in
TextField("Enter Name", text: $row.name)
}
}
}
}
struct Row: Identifiable, Hashable {
let id = UUID()
var name: String
}
To make this sortable, I would need to pass a sortOrder: binding to Table, as well as well as manually sorting the rows array in onChange(of: sortOrder) { ... }.
However, this doesn't work:
@State var sortOrder: [KeyPathComparator<Binding<Row>>] = []
var body: some View {
Table($rows, sortOrder: $sortOrder) {
TableColumn("Name", value: \.wrappedValue.name) { $row in
TextField("Enter Name", text: $row.name)
}
}
.onChange(of: sortOrder) { _, sortOrder in
rows.sort(using: sortOrder) // error
}
}
Instance method
sort(using:)requires the typesRowandBinding<Row>be equivalent
I understand that this is because I am trying to sort an array of Rows using sort comparators that compare Binding<Row>s.
However, the Table initialiser requires that the type of sortOrder: to be
Binding<[KeyPathComparator<Binding<Row>>]>
because this is a table of Binding<Row>s.
How can I sort the rows in onChange? Perhaps there is a way to convert [KeyPathComparator<Binding<Row>>] to [KeyPathComparator<Row>]?
Just in case this is relevant, I only want the table to be re-sorted when sortOrder changes. I do not want the table to be re-sorted when some row's name is edited.