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