AARON SMITH’S CODE ENDEAVOR

Archive for the 'GDKit' Category

Simplifying iPhone UITableViewDataSource

I’ve been working the last couple weeks on an iPhone app. I’ve noticed that whenever I’m writing code that implements the UITableViewDataSource protocol it’s always the same code.

As I’ve been working I’ve been slowly coming back through all my code and writing re-usable objects and refactoring to use these new objects.

What I wanted was a (kind of) flex / flash like data provider object. This data provider implements the table view data source and has some nice convenience methods.

There’s three objects:

1. UITableViewDataProvider - the data source for a UITableView. It manages “groups” and contains a few accessor methods.

2. UITableViewGroup - the group manages a set of rows. And you can associate the section header titles and footer titles with the group.

3. UITableViewRow - a single row object contains a generic object for data. And it contains the code that creates and returns the “cell” for the table.

Here’s how you setup a data provider:

- (void) prepareTableData {
	tableData = [[UITableViewDataProvider alloc] init]; //table data is a member var
 
	UITableViewGroup * group1 = [UITableViewGroup group];
	ACExploreResultRow * row1 = [ACExploreResultRow row];
	ACSearchResultItem * item1 = [ACSearchResultItem itemWithTitle:@"Tag 3" andDesc:@"Desc" andThumb:[UIImage imageNamed:@"thumb.png"] andLarge:[UIImage imageNamed:@"large.png"]];
	[item1 setRating:2.3];
	[row1 setData:item1];
 
	ACExploreResultRow * row2 = [ACExploreResultRow row];
	ACSearchResultItem * item2 = [ACSearchResultItem itemWithTitle:@"Tag 4" andDesc:@"Desc" andThumb:[UIImage imageNamed:@"thumb.png"] andLarge:[UIImage imageNamed:@"large.png"]];
	[item2 setRating:3.5];
	[row2 setData:item2];
 
	[group1 addRow:row1];
	[group1 addRow:row2];
	[tableData addGroup:group1];
 
	[tableView setDataSource:tableData];
}

The only thing to point out is that the rows I’m creating are of type “ACExploreResultRow” which extends UITableViewRow. That row class is in charge of creating the cell to display.

Here’s the implementation for that class:

@implementation ACExploreResultRow
 
+ (ACExploreResultRow *) row {
	ACExploreResultRow * row = [[ACExploreResultRow alloc] init];
	return [row autorelease];
}
 
- (UITableViewCell *) cellForTable:(UITableView *) _tableView {
	UITableViewCell * cell = [super cellForTable:_tableView];
	ACSearchResultItem * d = (ACSearchResultItem *)data;
	[cell setText:[d title]];
	[cell setImage:[d thumb]];
	return cell;
}
 
@end

This ends up being a really good place for the cell creation logic. In this class I’m using a straight up UITableViewCell, but the idea is that you could create your own subclassed UITableViewCell and use that instead. It’s also a good pattern for re-using your cells and rows or putting the cells in nibs.

Another benefit for doing it like this is that the data provider has methods for getting the data object associated with a row. As an example, your view controller will still implement the UITableViewDelegate protocol, and you’d use those hooks like normal.

- (void) tableView:(UITableView *) _tableView didSelectRowAtIndexPath:(NSIndexPath *) indexPath {
	ACSearchResultItem * item = (ACSearchResultItem *)[tableData dataForIndexPath:indexPath];
	//yay we have data with one line of code!
}

You can find the code and a sample project in gdkit.

No comments

GDKit: A Cocoa Framework

As I’ve been writing Gity, I’ve been extracting pieces from it for a Cocoa app framework. It ended up being really nice. It’s kind of an equivalent Guttershark framework, but kind of not.

It’s pretty early right now, so there aren’t many utilities, or those types of general classes. But what is in here - and this is the good stuff - is the core for writing Cocoa apps, keeping them simple, logical, and organized. I’ve simplified and provided a pattern for writing maintainable cocoa apps, as well as a pattern for making your app Grand Central Dispatch friendly (see the docs for GDOperationsController).

It will compile for 10.5+ in XCode 3+. I haven’t tested all configurations of Mac OS / XCode, but there shouldn’t be anything in it that would cause problems. It’s all memory managed and should fit in fine with garbage collection.

It’s available on the gitweb page. Documentation is here. Examples are included in the repository.

So if you want to see how Gity is built, take a look at the examples in the repo. They only show the bare (really bare) minimum setup but you can probably see how to continue on from there. And make sure you inspect nibs in the example projects.

No comments