views:

70

answers:

4

I have a grouped UITableView that has 3 sections and a number of cells in each section that each need to be a different custom cell, with different display requirements.

I currently have a large if statement in cellForRowAtIndexPath, with each branch instantiating and returning the appropriate custom cell based on interrogating the indexPath's section and row properties. e.g.

if (indexPath.section == 0 && indexPath.row == 0) {
    // instantiate and return cell A
} else if (indexPath.section == 1 && indexPath.row == 2) {
    // instantiate and return cell B
} //etc etc

What is best practice for this scenario? A large if statement does the job, but is it the best implementation?

A: 

I think this is pretty much common practice. Just be sure that you specify a unique cell identifier for those different cells. So that caching of the cells works properly.

St3fan
+1  A: 

One method I've used once or twice is a nested series of NSArray objects that I initialize in viewDidLoad:

// sec<n>Row<n>Cell are IB Outlets to UITableViewCell objects defined in your .xib
NSArray *firstSectionRows = [[NSArray alloc] initWithObjects: sec1row1Cell, sec1row2cell, nil];
NSArray *secondSectionRows = [[NSArray alloc] initWithObjects: sec2row1Cell, sec2row2cell, nil];

// cellTree is an instance variable
cellTree = [[NSArray alloc] initWithObjects: firstSectionRows, secondSectionRows, nil];
[firstSectionRows release];
[secondSectionRows release];

Then in your tableView:cellForRowAtIndexPath: method would look like this:

...
return [[cellTree objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
...

This assumes that each of your cells is unique, in which case you don't even need to try and dequeue reusable cells. If you have more than one of the same type of cell in any section, you'll have to create/dequeue them appropriately and assign them a unique cell-type identifier.

If you have a large or complicated structure you might be able to do your array setup in a .plist file and use NSArray's initWithContentsOfFile: method to read it in. However you will have to do some kind of KVC magic to get cell objects from the strings in your array:

return [self valueForKey:[[cellTree objectAtIndex:indexPath.section] objectAtIndex:indexPath.row]];
Frank Schmitt
+1  A: 

On complex table views I've considered splitting up the UITableViewDataSource routines into sub-delegates, one delegate for each section. So for 3 sections, I would create 3 separate objects each one responsible for providing the UITableViewDataSource methods for that section of the table. Then the UITableView's delegate just dispatches to one of the appropriate sub-delegates depending on which section the request is for.

progrmr
+1  A: 

By far the best way to do this is described in this post from Cocoa With Love. Basically it's a custom controller for each cell type but it ends up being really simple to implement.

Steven Canfield
Thanks for the link, great blog post. I like the way all the cell handling logic is in a superclassed controller - means that the specific table view controllers are only responsible for building the table structure. I still have some issues with how to manage FirstResponder state when in the context of a cell though - especially when taps happen outside of the current cell. I'm currently working through that.
Robert Conn