Displaying NSCell subclasses for different NSOutlineView levels

June 09, 2007

Say you have an NSOutlineView in your application that displays objects of a certain type in level 0, objects of another type in level 1, and so on. Although you can just use a standard text cell to display information about these objects, eventually you might want to make custom NSCell subclasses to gain more control over what’s being displayed. This is easy to do, but you will have to subclass one thing; NSTableColumn. The short code snippet below shows the only method you need to override.

- (id)dataCellForRow:(int)row;
{
	NSOutlineView *outlineView = (NSOutlineView *)[self tableView];
	int level = [outlineView levelForRow:row];

	return ( level == 0 ) ? (id)[self cellTypeA] : (id)[self cellTypeB];
}

In this example, you’re simply calling an accessor method for cellTypeA or cellTypeB depending on the level of the outline view. cellTypeA and cellTypeB can be whatever kind of NSCell you need, either one of the Cocoa types or a subclass you’ve defined. Since NSCell instances are typically re-used between rows, it’s safe to simply store these two cells as instance variables in your class. If you needed to though, you could create them on demand, or even get them from another part of your application.

When you’re done, drag the header into Interface Builder, click the table column in your nib so it shows up in the inspector, and choose your subclass under Custom Class. Remember to override initWithCoder or awakeFromNib if you’re setting any instance variables, since the default NSTableColumn initializer will never be called if it’s loaded from a nib.

NSTableView works exactly the same way, except you’ll need to invent your own way of determining which cell to return for a row.

Marc Charbonneau is a mobile software engineer in Portland, OR. Want to reply to this article? Get in touch on Twitter @mbcharbonneau.