objective-ccocoanstableviewnsoutlineview

Empty Cells in View Based NSOutlineView


UPDATE: Link to source complete source code (download)

I am trying to implement a view based NSOutlineView (Sourcelist), but I have run into problems. To illustrate, I have created a minimalistic example.

I have a simple class called Person. Each person has a name (NSString) and maybe also some children (NSArray). I have added an NSOutlineView, hooked it up to an IBOutlet, set myself as DataSource, and implemented the NSOutlineViewDataSource methods.

First consider the case of a CELL BASED NSOutlineView:

- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
    // We are at the root
    if (!item)
    {
        return [self.persons count];

    }

    // We are at an internal node
    Person *person = (Person *)item;
    return [person.children count];
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
    // We are at the root
    if (!item)
    {
        return self.persons[index];
    }

    // We are at an internal node
    Person *person = (Person *)item;
    return person.children[index];
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
    Person *person = (Person *)item;
    if ([person.children count] > 0)
    {
        return YES;
    }
    return NO;
}

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
    Person *person = (Person *)item;
    return person.name;
}

It works just as I expected:

enter image description here

However, if I go and change the NSOutlineView to VIEW BASED, things look very different. Now all the names are replaced by "Table View Cell". I have tried to fix the problem by returning an NSTableCellView instead:

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
    Person *person = (Person *)item;

    NSTableCellView *tableCellView = [outlineView makeViewWithIdentifier:@"PersonCell" owner:self];
    tableCellView.textField.stringValue = person.name;

    return tableCellView;
}

Without making further changes, this doesn't change anything. When I change the identifier of the TableCellView in my NSOutlineView to PersonCell,

enter image description here enter image description here

all the cells end up empty. In fact, adding a simple NSLog statement in the outlineView:objectValueForTableColumn:byItem: function reveals that the function is never even called.

This approached has worked for me with standard NSTableViews, and since NSOutlineView is a subclass of NSTableView, I expected the same behavior here.

Any help is greatly appreciated.

Thanks!

/Michael Knudsen


Solution

  • I think the corresponding method to return the proper view objects for each row is

    - (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
    

    and not

    - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
    

    You return a view, not an objectValue in view based table views.

    So it should work using:

    - (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
        Person *person = (Person *)item;
        NSTableCellView *tableCellView = [outlineView makeViewWithIdentifier:@"PersonCell" owner:self];
        tableCellView.textField.stringValue = person.name;
    
        return tableCellView;
    }