IOS and Rails web dev at Intotheweb. Follow me on twitter @brunow
UITableView Dynamic cell mapping like Restkit[EDIT]
I love the JSON object mapping from RestKit and recently RestKit create a new library that map dynamically object property with cell ui property. But i thought that the RestKit solution was too complicated. So I decide to do my own cell mapper. You can found BaseKit on Github.
Add BaseKit to your project
That's really easy. Just drag the dir Code/Core, Code/View and Code/CellMapping into your project.
Next step create an object that will store data from the cell.
Create a class called Movie.
Movie.h
@interface Movie : NSObject
@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) NSString *subtitle;
@property (nonatomic, readonly) NSString *imageName;
+ (id)itemWithTitle:(NSString *)title subtitle:(NSString *)subtitle;
@end
Movie.m
@implementation Movie
@synthesize title = _title;
@synthesize subtitle = _subtitle;
- (void)dealloc {
self.title = nil;
self.subtitle = nil;
[super dealloc];
}
+ (id)itemWithTitle:(NSString *)title subtitle:(NSString *)subtitle {
Item *item = [[self alloc] init];
item.title = title;
item.subtitle = subtitle;
return [item autorelease];
}
- (NSString *)imageName {
return @"tux.png";
}
@end
The table view cell
Create one simple cell called MovieViewCell that inherit from UITableViewCell. The only thing you have to do here, is:
+ (UITableViewCellStyle)cellStyle {
return UITableViewCellStyleSubtitle;
}
Sa that you can use cell.detailTextLabel and cell.imageView properties. Read the UItableViewCell category to learn more about that.
Last step: create the table view controller
TableViewControllerExample.h
@interface TableViewControllerExample : UITableViewController<BKTableModelDataSource>
@property (nonatomic, retain) BKTableModel *tableModel;
@property (nonatomic, retain) NSArray *items;
@end
TableViewControllerExample.m
@implementation TableViewControllerExample
@synthesize tableModel = _tableModel;
@synthesize items = _items;
- (void)viewDidLoad {
[super viewDidLoad];
self.items = [NSArray arrayWithObjects:
[Item itemWithTitle:@"Movie1" subtitle:@"First movie"],
[Item itemWithTitle:@"Movie2" subtitle:@"Second movie"],
[Item itemWithTitle:@"Book1" subtitle:nil],
nil];
self.tableModel = [BKTableModel tableModelForTableView:self.tableView];
[BKCellMapping mappingForObjectClass:[Movie class] block:^(BKCellMapping *cellMapping) {
[cellMapping mapKeyPath:@"title" toAttribute:@"textLabel.text"];
[cellMapping mapKeyPath:@"subtitle" toAttribute:@"detailTextLabel.text"];
[cellMapping mapKeyPath:@"imageName" toAttribute:@"imageView.image" valueBlock:^id(NSString *value) {
// Because imageName is of type NSString and imageView.image of type UIImage
return [UIImage imageNamed:value];
}];
[cellMapping mapObjectToCellClass:[MovieViewCell class]];
[self.tableModel registerMapping:cellMapping];
}];
[self.tableModel objectForRowAtIndexPathWithBlock:^id(NSIndexPath *indexPath) {
return [self.items objectAtIndex:indexPath.row];
}];
}
- (void)viewDidUnload {
[super viewDidUnload];
self.tableModel = nil;
self.items = nil;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self.tableModel cellForRowAtIndexPath:indexPath];
}
BKCellMapping has a lot of more fonctionalities. For example loading nib and perform dynamic mapping. You can found more example here.