MHNibTableViewCell, Easily Load Table View Cells from NIB Files

Warning:┬áThis is an old class that is only useful on iOS 4 or lower. These days you should use UITableView’s new registerNib:forCellReuseIdentifier: method instead, or even easier, use storyboards with prototype cells.

* * *

Most iOS projects use a table view somewhere. Often the standard table view cell types are sufficient to present your data, but sometimes you need more complex cells. You can do this programmatically but I prefer to use Interface Builder.

After typing the same nib loading code over and over, I decided to abstract it into a class, MHNibTableViewCell. This class makes it very easy to use table view cells that are completely designed in Interface Builder.

Make a subclass

As its name implies, MHNibTableViewCell extends from UITableViewCell. To use it you need to make your own subclass and a nib file. If you name your subclass MyCell, the corresponding nib file must be named MyCell.xib.

Suppose our cell will have two labels and an image view. Its definition then looks like this:

@interface MyCell : MHNibTableViewCell
{
}
 
@property (nonatomic, retain) IBOutlet UILabel* topLabel;
@property (nonatomic, retain) IBOutlet UILabel* bottomLabel;
@property (nonatomic, retain) IBOutlet UIImageView* customImageView;
 
@end

In your table view’s data source, you would then do:

- (UITableViewCell*)tableView:(UITableView*)theTableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
	MyCell* cell = [MyCell cellForTable:theTableView withOwner:nil];
 
	// Configure the cell, based on your model data
	cell.topLabel.text = ...;
	cell.bottomLabel.text = ...;
	cell.customImageView.image = ...;
 
	return cell;
}

The magic happens in +cellForTable:withOwner:. This method automatically loads the nib, connects any outlets, and re-uses a queued cell if possible. Easy peasy. You just have to load your model data into the cell.

Make a nib file

Creating the nib file is similarly straightforward. You create an empty nib and add a single Table View Cell.

You don’t have to set the cell’s identifier (the name of your subclass will be used as the reuse identifier instead), but you do have to set the class name to the name of your MBNibTableView subclass (under the “Custom Class” heading in Interface Builder).

MyCell.xib looks like this in Xcode 4′s Interface Builder (click to enlarge):

MyCell.xib in Interface Builder

The nib has four items in it (besides File’s Owner and First Responder):

  • The Table View Cell itself. Its content view has three subviews: two labels and an image view. These subviews are connected to MyCell‘s topLabel, bottomLabel and customImageView outlets. The content view is transparent.
  • A UIImageView with an arrow image. This view is connected to the cell’s accessoryView outlet.
  • A UIImageView with a gray gradient image, which is connected to the cell’s backgroundView outlet.
  • A UIImageView with a green gradient image, connected to the cell’s selectedBackgroundView outlet.

Because we connected the arrow image view to accessoryView, the arrow will always show up as the cell’s accessory (on the right of the cell). Likewise, the gray gradient image will be shown below the content view because we connected it to backgroundView. And when you tap a row in the table, the green gradient image will be drawn to indicate that the row is selected.

Respect UITableViewCell’s design

Note that we did not add the arrow image directly as a subview to the table view! Instead, we added a separate view and connected it to the accessoryView outlet. Adding it as a subview might appear to achieve the same effect, but there is a subtle difference.

UITableViewCell already does a lot of work for you behind the scenes. When the table goes into editing mode, for example, whatever is in the accessory view will either slide out of the screen or fade out, in order to make room for the Delete button. You probably want to keep that kind of behavior.

Regular content should be added to the cell’s contentView (that is what you add your subviews to in Interface Builder). Things that function as accessory buttons should be connected to accessoryView, and background images should be connected to the backgroundView and selectedBackgroundView outlets. Follow those simple rules and your table view cells will work as intended.

Even though UITableView already has an imageView property, I added a customImageView outlet to MyCell. The default imageView seems to be intended to be used with the standard table view styles. On custom table view cells, I prefer to use my own image view instead of the default one, as this gives me more control over where it appears and how big it is.

Note that it’s a good idea to set up autosizing on the content view. Table view cells can change size for a number of reasons. If we set an accessory on the cell or put the table in editing mode, the content size shrinks to make room. If your app supports both portrait and landscape mode, you want the cell contents to adjust when the user rotates the device.

The demo project

I have made a demo project that illustrates how to use MHNibTableViewCell. This project shows a variety of ways to use nib files to create custom table view cells, including things that don’t work so well.

A well-known tutorial on making custom cells using images is Matt Gallagher’s EasyCustomTable example. Just for the fun of it, I rewrote his code using nibs and also put that in the demo project. On OS 4.0 and later this shouldn’t be any slower than his method because the nib file is loaded only once and then cached in memory. (The images in the MyCell example above are also taken from his article.)

If you’re interested in using nibs to spruce up your table view cells, then have a look at the code to learn about what works and what doesn’t.

Comments

  1. Alexander says:

    Very nice post! This was really helpful. Can I use the MHNibTableViewCel in my own projects?

  2. Matthijs says:

    Hi Alexander, the code is licensed under the terms of the MIT license. Basically that means you can do with it whatever you want, except sue me. ;-)

  3. Rachel says:

    Thank you! This is extremely useful.

Leave a Reply

Your email address is required but will not be visible to others.

 *
 *