I need to have a proper, multi-line text editor in a table (SwiftUI Table).
Requirement is not a typical spreadsheet, it is rather a table with cells of larger size, mostly for editing multi-line textual content. Expectation is a dozen or two of columns and potentially many rows. Some columns might contain single simple scalar values, those might be using for sorting, for example.
Here is a simple (wrong) code snippet that demonstrates what I am trying to achieve at this moment:
struct Thing: Identifiable {
var id: Int
var text: String
init(id: Int, text: String="") {
self.id = id
self.text = text
}
}
var data = [
Thing(id: 1, text: "one"),
Thing(id: 2, text: "two"),
Thing(id: 3, text: "three"),
]
struct ContentView: View {
var body: some View {
VStack {
Text("Hello, world!")
.padding()
Table(data) {
TableColumn("ID") { row in Text(String(row.id)) }
// Error: Cannot convert value of type 'String' to expected argument type 'Binding<String>'
TableColumn("Text") { row in TextEditor(text: row.text) }
}
}
}
}
Question: What is the proper way of defining that the row.text
is a binding in this case?
Side note: I can not use key paths, since at the end the Thing
will also be some dynamic structure not known at compile time - the structure will be editable by the user.
What is the proper way of defining that the row.text is a binding in this case?
As far as I read the docs and watched the sample code, SwiftUI.Table
does not give us a quick way to make some cell editable.
One possible solution would be something like this:
(Not sure, if this code would work as expected.)
struct ContentView: View {
@State var data = [
Thing(id: 1, text: "one"),
Thing(id: 2, text: "two"),
Thing(id: 3, text: "three"),
]
var body: some View {
VStack {
Text("Hello, world!")
.padding()
Table(data) {
TableColumn("ID") { row in Text(String(row.id)) }
TableColumn("Text") { row in
//`id` needs to keep the position in `data`
TextEditor(text: $data[row.id-1].text)
}
}
}
}
}
at the end the
Thing
will also be some dynamic structure not known at compile time
That sounds like you should better stay in the AppKit world a little more, until SwiftUI gives us more convenient ways to write some dynamic things.