Loading UITableViewCells from a nib file

Jonah Williams ·

While working on iPhone applications I have found it useful to load as much of the UI layout and styling from nib files as possible. As a result I often want to load the cells for a table view from a nib file and created a factory class to handle this behavior every time I want to reuse it.
When I need to use a custom cell in a table view I add a cell factory as a property on the view’s controller and select a cell to use by setting that property when constructing the controller. This often allows me to reuse a single factory across multiple controllers so I don’t have to repeat myself by including duplicate references to the same cell nib in every controller.

@interface CellFactory : NSObject {
	Class cellClass;
	NSString *nibName;
	NSString *identifier;
}

+ (CellFactory *) factoryWithClass:(Class) theCellClass andNib:(NSString *)theNibName andIdentifier:(NSString *)theIdentifier;

@property(nonatomic, retain) Class cellClass;
@property(nonatomic, retain) NSString *nibName;
@property(nonatomic, retain) NSString *identifier;

- (UITableViewCell *) createCell;
- (UITableViewCell *) createCellWithOwner:(id)owner;

@end

@implementation CellFactory

@synthesize cellClass, nibName, identifier;

+ (CellFactory *) factoryWithClass:(Class) theCellClass andNib:(NSString *)theNibName andIdentifier:(NSString *)theIdentifier {
	CellFactory *factory = [[[CellFactory alloc] init] autorelease];
	factory.cellClass = theCellClass;
	factory.nibName = theNibName;
	factory.identifier = theIdentifier;
	return factory;
}

- (UITableViewCell *) createCellWithOwner:(id)owner {
	NSArray* nibContents = [[NSBundle mainBundle] loadNibNamed:self.nibName owner:owner options:nil];
    for (id nibItem in nibContents) {
        if ([nibItem isKindOfClass:self.cellClass] && (self.identifier == nil || [[(UITableViewCell *)nibItem reuseIdentifier] isEqualToString: self.identifier])) {
            return (UITableViewCell *) nibItem;
        }
    }
    return nil;
}

- (UITableViewCell *) createCell {
    return [self createCellWithOwner:self];
}

@end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
	UITableViewCell *cell;
	cell = [self.tableView dequeueReusableCellWithIdentifier:self.cellFactory.identifier];
	if (cell == nil) {
		cell = [self.cellFactory createCell];
	}
	return cell;
}

An example app using this factory is available in the Carbon Five svn repository: http://svn.carbonfive.com/public/jonah/CellFactoryExample