简体   繁体   中英

Getting NSTreeController Data on NSOutlineView selection

I've built an NSOutlineView that gets dynamically updated data from an NSTreeController and that all works fine. What I can't seem to do is work backwards from there based on a user selection in the NSOutlineView.

    var deviceStore = [TreeNode]()

is my backing datastore that is updated in real-time it is an array of Device Objects, which may )or may not) contain an array of Service objects as children.

This all works. But when I select a row in the Outline View, I need to work my way back to the original object in the deviceStore -- or, at the very least, get the displayed data from the OutlineView so that I can walk the deviceStore to find the original item.

What I've got is func outlineViewSelectionDidChange(_ notification: Notification) {} which is called when a selection is made, and I can, from that, extract the NSTreeController TreeNode via treeController.selectedNodes but from there, I am in the weeds. The selectedNodes is the complete array of the selected Node, so if it's a child (leaf) node, it includes its parent node, and all its siblings.

Give then Table shown here: 轮廓视图

The selectedNodes array looks like this:

<NSTreeControllerTreeNode: 0x6080000c4590>, child nodes {
    0:<NSTreeControllerTreeNode: 0x6000000ca6b0>, child nodes {
        0:<NSTreeControllerTreeNode: 0x6000000caf70>, child nodes {}
        1:<NSTreeControllerTreeNode: 0x6000000cafe0>, child nodes {}
        2:<NSTreeControllerTreeNode: 0x6000000cb050>, child nodes {}
    }
    1:<NSTreeControllerTreeNode: 0x6080000d1790>, child nodes {
        0:<NSTreeControllerTreeNode: 0x6000000cce80>, child nodes {}
    }
}

And the selectedIndex is 4.

I can't see how to get back to what, in my data model, would be deviceStore[0].serviceStore[2] from this information.

If I could retrieve the value in the Service ID column from the selected Row, I could simply walk the deviceStore tree to find it.

I'm sure there's a simply, elegant, easy way to do this that I just haven't found yet, but being new to NSTreeController s and NSOutlineView s I'm lost.

You may try to access directly the associated object(s) like this:

let selectedService = treeController.selectedObjects.first as? Service

The docs are here .

also make sure your NSTreeController is correctly configured to use your class' objects:

在此处输入图片说明

Alternatively (if you want to work directly with your data source) you may want to get the index path of the selected object in the NSTreeController :

var selectionIndexPath: IndexPath? { get }

I use following with Core data,

func outlineViewSelectionDidChange(_ notification: Notification) {
    let item = outlineView.item(atRow: outlineView.selectedRow) as! NSTreeNode
    let fileItem = item.representedObject as! FileItemMO

    // Do what you need to do with object fileItem

}

I was never able to actually get back to the TreeController backing-store data baed on where the user clicks in the TreeView. What I was able to do was to work backwards to the data though.

func outlineViewSelectionDidChange(_ notification: Notification) {
    let selectedIndex = (notification.object as AnyObject).selectedRow!
    let selCol1 = outlineView.view(atColumn: 0, row: selectedIndex, makeIfNecessary: false)?.subviews.last as! NSTextField
    let selCol2 = outlineView.view(atColumn: 1, row: selectedIndex, makeIfNecessary: false)?.subviews.last as! NSTextField

    let devName = selCol1.stringValue
    let devID = selCol2.stringValue
...
}

I could then 'walk' the deviceStrore array until I found the devName and devID in it, and deal with it accordingly.

Probably not the most elegant solution, but at least it finally works.

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