views:

94

answers:

2

I'm having a hard time scraping together enough snippets of knowledge to implement an NSOutlineView with a static, never-changing structure defined in an NSArray. This link has been great, but it's not helping me grasp submenus. I'm thinking they're just nested NSArrays, but I have no clear idea.

Let's say we have an NSArray inside an NSArray, defined as

NSArray *subarray = [[NSArray alloc] initWithObjects:@"2.1", @"2.2", @"2.3", @"2.4", @"2.5", nil];
NSArray *ovStructure = [[NSArray alloc] initWithObjects:@"1", subarray, @"3", nil];

The text is defined in outlineView:objectValueForTableColumn:byItem:.

- (id)outlineView:(NSOutlineView *)ov objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)ovItem
{
    if ([[[tableColumn headerCell] stringValue] compare:@"Key"] == NSOrderedSame)
    {
        // Return the key for this item. First, get the parent array or dictionary.
        // If the parent is nil, then that must be root, so we'll get the root
        // dictionary.

        id parentObject = [ov parentForItem:ovItem] ? [ov parentForItem:ovItem] : ovStructure;

    if ([parentObject isKindOfClass:[NSArray class]])
        {
            // Arrays don't have keys (usually), so we have to use a name
            // based on the index of the object.

        NSLog([NSString stringWithFormat:@"%@", ovItem]);
            //return [NSString stringWithFormat:@"Item %d", [parentObject indexOfObject:ovItem]];
        return (NSString *) [ovStructure objectAtIndex:[ovStructure indexOfObject:ovItem]];
        }
    }
    else
    {
        // Return the value for the key. If this is a string, just return that.

        if ([ovItem isKindOfClass:[NSString class]])
        {
            return ovItem;
        }
        else if ([ovItem isKindOfClass:[NSDictionary class]])
        {
            return [NSString stringWithFormat:@"%d items", [ovItem count]];
        }
        else if ([ovItem isKindOfClass:[NSArray class]])
        {
            return [NSString stringWithFormat:@"%d items", [ovItem count]];
        }
    }

    return nil;
}

The result is '1', '(' (expandable), and '3'. NSLog shows the array starting with '(', hence the second item. Expanding it causes a crash due to going 'beyond bounds.' I tried using parentForItem: but couldn't figure out what to compare the result to.

What am I missing?

A: 

The example behind the link you included shows an NSDictionary taking care of the subarray stuff, if I'm reading it correctly. So I think your ovStructure should not be an array but a dictionary. But, more fundamentally, I think you should really look into NSTreeController. Unfortunately, NSTreeController is notoriously hard to work with, but improvements were made last year and even I got it working in the end. Good luck.

Elise van Looij
A: 

Some brave soul over at CocoaDev Forums released a fully-functioning example of a tree-based NSOutlineView. This is, to my knowledge, the only basic example of this UI control outside of Apple.

spamguy