I'm playing with the code below on Playground. I want to update the View's State array students when a tableview edit is done.
I'm not sure if I have to manually listen to events of NSTextField and then update the state variable. Is there a way to bind the TextField to the state variable?
import PlaygroundSupport
import SwiftUI
struct TV: NSViewRepresentable {
@Binding var students: Array<String>
var updating: Bool = false
var tv: NSTableView = NSTableView()
func makeNSView(context: Context) -> NSScrollView {
let sv = NSScrollView()
sv.documentView = tv
tv.gridStyleMask = .solidHorizontalGridLineMask
tv.usesAlternatingRowBackgroundColors = true
tv.allowsMultipleSelection = true
let col = NSTableColumn(identifier: NSUserInterfaceItemIdentifier(rawValue: "Name"))
col.title = "Name"
_ = tv.addTableColumn(col)
_ = tv.delegate = context.coordinator
tv.dataSource = context.coordinator
NotificationCenter.default.addObserver(context.coordinator, selector: #selector(Coordinator.onAddClicked(_:)), name: Notification.Name(rawValue: "onAddClicked"), object: nil)
return sv
}
func updateNSView(_ nsView: NSScrollView, context: Context) {
}
func makeCoordinator() -> Coordinator {
Coordinator(self, students: self._students)
}
class Coordinator: NSObject, NSTableViewDelegate, NSTableViewDataSource, NSTextFieldDelegate {
var parent: TV
@Binding var students: Array<String>
init(_ parent: TV, students: Binding<Array<String>>) {
self.parent = parent
self._students = students
}
@objc func onAddClicked(_ notification: Notification) {
print("onAddClicked")
let tableView = parent.tv
self.students.append("")
tableView.reloadData()
tableView.editColumn(0, row: students.count - 1, with: nil, select: true)
}
func numberOfRows(in tableView: NSTableView) -> Int {
print("numberOfRows \(students.count)")
return students.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
var result = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("MyView"), owner: self) as! NSTextField?
if(result == nil) {
result = NSTextField()
result?.identifier = NSUserInterfaceItemIdentifier("MyView")
result?.isEditable = true
result?.delegate = self
}
result?.stringValue = self.students[row]
return result
}
}
}
struct view: View {
@State var students = ["John", "Mary", "Bob"]
@State var minusDisabled: Bool = true
var body: some View {
Group {
VStack(alignment: .leading) {
Text("Test")
TV(students: self.$students).frame(width: 300, height: 500)
HStack {
Button(action: {
NotificationCenter.default.post(name: Notification.Name(rawValue: "onAddClicked"), object: nil)
}) {
Text("+")
}.buttonStyle(BorderedButtonStyle())
Button(action: {
}) {
Text("-")
}.buttonStyle(BorderedButtonStyle())
.disabled(self.minusDisabled)
}
}.fixedSize()
VStack {
ForEach(self.students, id: \.self) { student in
Text(student)
}
}.frame(height: 200)
}
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.setLiveView(view().frame(width: 500, height: 800))