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