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