5
votes

What's the most efficient way to expand all objects of a specific class in a NSOutlineView? (The datasource of my outline view is a NSTreeController).

Let's say I have

classA
classA
    - classA
        - classC
        - classC
    - classB
        - classC
        - classC
classB
   - classC

I want to expand classA objects only. Do I need to iterate through the entire three checking which class belong each object?

UPDATE Sorry I have to make a correction. The outlineView objects are NSTreeNodes from NSTreeController data source. And only the "representedObject" are those my custom classes.

So the structure with those classes is correct, but they are not directly accessible as nodes of the outline view.

3

3 Answers

3
votes

For what it's worth, the important "glue" I mentioned in the comment is more or less straight from this great blog post: Saving the expand state of a NSOutlineView.

I took all the classes in my tree, and made them subclasses of an abstract class with an expanded property, so every representedObject in an NSTreeNode has expanded as a property.

But you may not even need to do that if you don't care about persisting expanded in your data model.

The straightforward thing to do is to just iterate the rows:

    for (NSUInteger row = 0; row < [outlineView numberOfRows]; row++)
    {
        // Expand item if it's an classA
        NSTreeNode* treeNode = [outlineView itemAtRow:row];
        if ([treeNode.representedObject isKindOfClass:[ClassA class]])
            [sender.animator expandItem:treeNode];
    }

... you'll notice that for loop borrows a lot of structure from the referenced blog post.

So I guess my answer is a lazy, "yes, iterate the whole tree." At least the displayed tree.

EDIT: For those who are a bit overzealous about MVC, I now feel it's necessary to specify that the above code should be in the class you use as the NSOutlineView controller, which would usually implement <NSOutlineViewDelegate>

0
votes

Sounds like a job for NSOutlineViewDelegate:

- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
    if ([[item representedObject] isMemberOfClass:[ClassA class]]) {
        [outlineView expandItem:item];
    }
}
-1
votes

Do I need to iterate through the entire three checking which class belong each object?

Yes, because that is, what you want to do.

But it is not that easy as in the A of stevesliva:

A. You should not iterate over the items of the outline view. It is a view. It has nothing to do with the data. I. e., if a node is closed, the descendants are not in the row list. This is because there is no row for them.

B. Instead iterate over the content of the tree controller. Controllers are made for data access, so it is the right place to access data. -arrangedObjects (NSTreeController) gives you access to the content.