Given model object, how to find index path in NSTreeController?
Asked Answered
D

2

9

Given model objects that NSTreeController represents, how do you find their index paths in the tree and subsequently select them? This seems to be a blindingly obvious problem, but I can't seem to find any reference to it. Any ideas?

Dehumidify answered 29/1, 2012 at 0:57 Comment(0)
I
21

There's no "easy" way, you have to walk the tree nodes and find a matching index path, something like:

Objective-C:

Category

@implementation NSTreeController (Additions)

- (NSIndexPath*)indexPathOfObject:(id)anObject
{
    return [self indexPathOfObject:anObject inNodes:[[self arrangedObjects] childNodes]];
}

- (NSIndexPath*)indexPathOfObject:(id)anObject inNodes:(NSArray*)nodes
{
    for(NSTreeNode* node in nodes)
    {
        if([[node representedObject] isEqual:anObject])
            return [node indexPath];
        if([[node childNodes] count])
        {
            NSIndexPath* path = [self indexPathOfObject:anObject inNodes:[node childNodes]];
            if(path)
                return path;
        }
    }
    return nil; 
}
@end    

Swift:

Extension

extension NSTreeController {

    func indexPathOfObject(anObject:NSObject) -> NSIndexPath? {
         return self.indexPathOfObject(anObject, nodes: self.arrangedObjects.childNodes)
    }

    func indexPathOfObject(anObject:NSObject, nodes:[NSTreeNode]!) -> NSIndexPath? {
         for node in nodes {
            if (anObject == node.representedObject as! NSObject)  {
                 return node.indexPath
            }
            if (node.childNodes != nil) {
                if let path:NSIndexPath = self.indexPathOfObject(anObject, nodes: node.childNodes)
                {
                     return path
                }
            }
        }
        return nil
    }
}
Insert answered 29/1, 2012 at 2:43 Comment(5)
Ouch, that's really inefficient. I'm thinking of writing a subclass of treecontroller that keeps a mapping between model and treenodes. Or perhaps a category on the model that keeps references to the associated treenode.Dehumidify
All you'd need to do in your subclass is to maintain a flat NSMutableArray of the tree nodes. You'd need to be careful that all modifications of the nodes are reflected in your array, of course.Insert
Hmm, I was thinking of a NSMutableDictionary mapping either the model object or the objectID to NSTreeNodes, since it seems more efficient for lookup. Is there any reason NSmutableArray might work betteR?Dehumidify
NSMutableDictionary would work fine. I would tend to store the NSIndexPath of the items rather than the tree node because I'm not sure if its guaranteed that NSTreeController always returns the same NSTreeNode per object.Insert
@Dehumidify Did you implement this then?Halfmoon
C
-1

Why not use the NSOutlineView to get the parent items like this:

NSMutableArray *selectedItemArray = [[NSMutableArray alloc] init];

[selectedItemArray addObject:[self.OutlineView itemAtRow:[self.OutlineView selectedRow]]];

while ([self.OutlineView parentForItem:[selectedItemArray lastObject]]) {
  [selectedItemArray addObject:[self.OutlineView parentForItem:[selectedItemArray lastObject]]];
}

NSString *selectedPath = @".";
while ([selectedItemArray count] > 0) {
  OBJECTtype *singleItem = [selectedItemArray lastObject];
  selectedPath = [selectedPath stringByAppendingString:[NSString stringWithFormat:@"/%@", singleItem.name]];
  selectedItemArray removeLastObject];
}

NSLog(@"Final Path: %@", selectedPath);

This will output: ./item1/item2/item3/...

I'm assuming you are looking for a file path here but you can adjust for whatever your data source may represent.

Carditis answered 11/2, 2014 at 21:41 Comment(1)
The question is looking for an NSIndexPath for any given object in the tree, so that you can change the tree controller's selectedIndexPath(s) to that one programmatically. You are assuming that the object is already selected. If so, you'd just get the selectionIndexPath from the tree controller!Glidden

© 2022 - 2024 — McMap. All rights reserved.