Different Cells in the Same Table View

Most non-game iOS applications will have a table view somewhere. Many of these table views are simple enough that the cells are identical (except, of course, for their contents).

Sometimes, though, you want to have different cells based on the nature of the object being represented in the cell. For example, consider an app to support a guild in World of Warcraft. You want your fellow guild members to be able to log in and manage their characters. In the game, most players have a preferred character termed a main (this is usually, though not always, the character they play the most). However, the game is incredibly diverse, so players often create other characters as well, called alternates (or alts for short).

In my little Moonwell Dancers app, I want to differentiate those two types of characters.

Creating the Cell Classes

This is fairly straightforward; in fact, if you've created custom table cells before, this is old hat. In Xcode, in your project, create a new Objective-C class with UITableViewCell chosen as the parent class. Do this for however many different type of table cells you intend to create (in my case, MainCharacterCell and AlternateCharacterCell.

Creating the XIB Files

The XIB files, of course, are where you do the layout for your table cells.

In Xcode, choose [menu]New File...[/menu] from the [menu]File[/menu] menu. Navigate to the [menu]User Interface[/menu] section under iOS, and choose the "Empty" option. The device family you choose doesn't matter. Give it the same name you gave the class above, and Xcode will create the XIB file.

In the XIB file itself, drag a "Table View Cell" from the object library onto the interface.

One key thing here is to provide each cell with an identifier (look in the Attributes inspector). I chose MainCell and AlternateCell as my identifiers.

Repeat this process for as many unique cells as you intend to create.

Modifying the Table View Controller

As you know, the method tableView:cellForRowAtIndexPath: is where you provide the cell for a particular position in the list. When doing custom cells, however, you need to first make sure the table view controller knows about your cells. You do this by registering them in the viewDidLoad method.

Partial Listing: TableViewController.m

- (void)viewDidLoad
    [super viewDidLoad];

    // Register main XIB for use with cells
    UINib *mainNib = [UINib nibWithNibName:@&;quot;MainCharacterCell&;quot; bundle:nil];
    [[self tableView] registerNib:mainNib forCellReuseIdentifier:@&;quot;MainCell&;quot;];

    // Register alternate XIB for use with cells
    UINib *alternateNib = [UINib nibWithNibName:@&;quot;AlternateCharacterCell&;quot; bundle:nil];
    [[self tableView] registerNib:alternateNib forCellReuseIdentifier:@&;quot;AlternateCell&;quot;];

    // Retrieve the characters to be displayed
    [self fetchCharacters];

With the NIB registration in place, now we are free to grab those reusable cells when providing a cell as the table view data source.

Partial Listing: TableViewController.m

// Cell will different between the main character and alternate characters
- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
    // Main is listed first
    if ([indexPath row] == 0)
        Character *character = main;

        MainCharacterCell *cell = [tableView dequeueReusableCellWithIdentifier:@&;quot;MainCell&;quot;
        // update the main character cell as desired
        return cell;
    // Alternates follow
        Character *character = [alternates objectAtIndex:([indexPath row] - 1)];

        AlternateCharacterCell *cell = [tableView dequeueReusableCellWithIdentifier:@&;quot;AlternateCell&;quot;
        // update the alternate character cell as desired
        return cell;

Obviously, your app logic will be different, but the principle is the same. Register the custom cells, make sure you reuse them, and then treat them like you would any other cell.