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