简体   繁体   中英

NSTableView Bindings doesn't work mac OS Swift

I'm trying to use cocoa bindings with nstableview and I have some problems with bind of parameter value of textfield: TextField绑定

I'm using this code, class:

class Person : NSObject {
var givenName:String
var familyName:String
var age = 0
var lol = 0

override init() {
    givenName = "given"
    familyName = "family"
    lol = 36
    super.init()
}

init(givenName:String, familyName:String, age:Int) {
    self.givenName = familyName
    self.familyName = givenName
    self.age = age
    self.lol = 36
    super.init()
} 

and view controller:

class ViewController: NSViewController {

@IBOutlet weak var tableViewL: NSTableView!

@IBOutlet var superResultsController: NSArrayController!

@objc dynamic var array =  [Person]()


override func viewDidLoad() {
    super.viewDidLoad()
    array.append(Person(givenName: "sas", familyName: "gfg", age: 10))
    array.append(Person(givenName: "sddsgds", familyName: "gfg", age: 10))
    array.append(Person(givenName: "uoijh", familyName: "gfg", age: 10))
    print(superResultsController.arrangedObjects)
}

I found that I can't bind textfield to any variable of my class - app crashes with bad_instruction error.

Here's my bindings of array controller and table view: NSArrayController: NSArrayController绑定

Table view: 表视图绑定

Cocoa Bindings are built on top of KVO. And KVO uses isa swizzling to insert hooks for automatic KVO notifications.

You have to mark those properties as dynamic so that the compiler doesn't optimize the calls to those properties. Making sure that, at runtime, getting/setting those properties will always flow through instance methods is essential for the KVO machinery to work.

Not marking those fields as dynamic might appear to work. When bindings are setup at runtime, the textfield will explicitly call the property to get the initial value to display. But any changes made to those properties will not send a KVO notification and the textfield will not update.

If you want to properly test this, add this code to the end of viewDidLoad :

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
     self.array[0].givenName = "Some Name"
     NSLog("Changed the name")
}

Run once, see that the table view doesn't update when the name changes. Add the dynamic to givenName on Person and run again, verify the table view updates.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM