Gram z poniższym kodem na placu zabaw. Chcę zaktualizować tablicę państwową widoku uczniów , gdy zostanie wykonany zestaw do tableview.

Nie jestem pewien, czy muszę ręcznie słuchać wydarzeń w NSTEXTFIELD, a następnie zaktualizować zmienną stanową. Czy istnieje sposób na wiązanie pola tekstowego do zmiennej państwa?

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))

1
Raisen 28 lipiec 2020, 01:56

1 odpowiedź

Najlepsza odpowiedź

Prawie na miejscu. Zrobiłeś koordynator jako delegat nstextfield, więc rącz dochody zmienił zwrotny

Testowany z XCode 11.4 / MacOS 10.15.5

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?.tag = row            // << link to modified student
    result?.stringValue = self.students[row]
    return result
}

func controlTextDidChange(_ obj: Notification) {
    guard let textField = obj.object as? NSTextField else { return }

    self.students[textField.tag] = textField.stringValue    // << update !!
}
1
Asperi 28 lipiec 2020, 03:57