What is the proper way to bind cell views to model objects in NSTableView / UITableView

那年仲夏 提交于 2019-12-13 05:53:20

问题


I have constructed a view-based NSTableView, programmatically (code-only, without XIB) following this, which is backed by an NSArrayController, created simply by: var controller = NSArrayController() and bound to the table by:

tableView.bind(NSContentBinding, toObject: controller, withKeyPath: "arrangedObjects", options: nil)
tableView.bind(NSSelectionIndexesBinding, toObject: controller, withKeyPath:"selectionIndexes", options: nil)
tableView.bind(NSSortDescriptorsBinding, toObject: controller, withKeyPath: "sortDescriptors", options: nil)

I only use the controller's methods to add/remove objects, and get them by: (controller.arrangedObjects as! NSArray)[index] . The items in the array are of a Class with String? or dynamic Double fields and they extend from NSObject.

Adding and removing rows inside the model automatically adds/removes the corresponding rows in the table, but I cannot bind the cell views to the items -and observe changes in their fields-. I tried to follow this and this with no luck. Final version of my cell view is like:

class PLTextCellView: NSTextField {
    init(columnName:String) {
        //.... erased...
        self.columnName = columnName
    }
    var columnName = ""

    var displayText:AnyObject {
        get {
            return stringValue
        }
        set(val) {
            stringValue = String(val)
        }
    }

    weak
    var item:PLItem? = nil

    override
    var objectValue: AnyObject? {
        didSet {
            item = objectValue as? PLItem
            if (item != nil) {
                Swift.print("item to bind is:\(item) ")
                unbind("displayText")
//                bind("displayText", toObject: self.item!, withKeyPath: columnName, options: [NSNullPlaceholderBindingOption:"--"])
                bind("displayText", toObject: self, withKeyPath: "objectValue."+columnName, options: [NSNullPlaceholderBindingOption:"--"])
            } else {
                Swift.print("unbinding... ")
                unbind("displayText")
            }
        }
    }

    deinit {
        unbind("displayText")
    }

    override
    func prepareForReuse() {
        unbind("displayText")
        super.prepareForReuse()
    }
    ///... erased ....
}

If I don't use any binding, I only get item object ids displayed on the table on each and every column, even if I explicitly set displayText (so something must be internally setting the text !!)

Question 1: If I use the commented/first bind line, each item object prints a different object id to the console -even if some represent the same object- and none of them exist in the controller! Why ?

Question 2: If I use the uncommented/second bind line, I get this error: An instance of ...item... was deallocated while key value observers were still registered with it.. This says I should not do binding/observing in the cell view, but the most convenient place seems the cell view (for MVC). I don't know a way to remove all -view-bindings in the model items in their deinits. (Interestingly, I even don't delete any items from the controller).

As I understand from the related questions and answers, this question also holds for UITableView's. So, what is the proper way to do the binding ?

来源:https://stackoverflow.com/questions/38047350/what-is-the-proper-way-to-bind-cell-views-to-model-objects-in-nstableview-uita

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!