The code examples for the iPhone SDK show only how to construct your table cells programatically. If you want to use InterfaceBuilder to make a proper layout which might also be resizable etc. you can use this ViewFactory to handle the creation and reusage of your table cells.
First create a new empty Interface Builder file. Design all the UITableViewCells you want, but they must be root objects so they can be found by the ViewFactory. Each cell MUST have its “identifier” field set. It is in fact its reuseIdentifier required to make a proper recycling of your cell possible.
Now create the ViewFactory, the header ViewFactory.h
@interface ViewFactory : NSObject {
NSMutableDictionary * viewTemplateStore;
}
- (id) initWithNib: (NSString*)aNibName;
- (UITableViewCell*)cellOfKind: (NSString*)theCellKind forTable: (UITableView*)aTableView;
@end
and the implementation ViewFactory.m
#import "ViewFactory.h"
@implementation ViewFactory
- (id) initWithNib: (NSString*)aNibName
{
if (self == [super init]) {
viewTemplateStore = [[NSMutableDictionary alloc] init];
NSArray * templates = [[NSBundle mainBundle] loadNibNamed:aNibName owner:self options:nil];
for (id template in templates) {
if ([template isKindOfClass:[UITableViewCell class]]) {
UITableViewCell * cellTemplate = (UITableViewCell *)template;
NSString * key = cellTemplate.reuseIdentifier;
if (key) {
[viewTemplateStore setObject:[NSKeyedArchiver
archivedDataWithRootObject:template]
forKey:key];
} else {
@throw [NSException exceptionWithName:@"Unknown cell"
reason:@"Cell has no reuseIdentifier"
userInfo:nil];
}
}
}
}
return self;
}
- (void) dealloc
{
[viewTemplateStore release];
[super dealloc];
}
- (UITableViewCell*)cellOfKind: (NSString*)theCellKind forTable: (UITableView*)aTableView
{
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:theCellKind];
if (!cell) {
NSData * cellData = [viewTemplateStore objectForKey:theCellKind];
if (cellData) {
cell = [NSKeyedUnarchiver unarchiveObjectWithData:cellData];
} else {
NSLog(@"Don't know nothing about cell of kind %@", theCellKind);
}
}
return cell;
}
@end
You have to make the ViewFactory instance available for your TableViews as a Singleton.
Whenever you want to fill you table cell in your UITableViewDataSource put this line in your method
- (UITableViewCell *)tableView: (UITableView *)aTableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
UITableViewCell * cell = [viewFactory cellOfKind:@"news" forTable:aTableView];
// Access the views using [cell viewWithTag:X] in the old way
return cell;
}
where “news” in this example is the value of the reuseIdentifier.
Internally I store each instance of the UITableViewCells as a template in a NSData archived format and make it accessible via its reuseIdentifier. So whenever cellOfKind:forTable: is called it looks into the reuseQueue of the given table if there is already an old table cell which can be reused or if it needs to instantiate a new one using the archived template to create the new table view cell.
This technique is much more flexible if you are using tables and I hope you will have fun using it.


