Improving iOS code with blocks and block programming

Programming languages are like people. Some are better at some things than others; some can do things other’s can’t. If they’re taken care of they get better over time. While I could look at a number of languages and frameworks for demonstration I’m particularly inspired by the relatively recent improvement of iOS development due to the magic of blocks.

Blocks are distinct sections of code that retain the state in which they were created and can be passed around like objects. This is something not inherent to the imperative programming language of C and often attributed to functional programming. Being that iOS is built on a foundation of C, much of the platform does not yet benefit from block programming. In order to demonstrate how blocks are changing the personality of iOS development I’ll first illustrate a significant limitation of iOS programming without blocks.

Delegates

Much of the platform is architected around something called delegates. The idea is that you create an object and you tell that object to delegate tasks for content and configuration to another class (In most cases the delegate is the same class instantiating the object.) The object will then ask the delegate object via callback methods that conform to it’s delegate protocol how to configure and populate itself.

A good example of this is a UITableView object. Here’s an example of building a table view the SDK way. It’s not important that you understand the code. Just skim it to get a sense for how verbose and disjointed it feels.

View verbose and disjointed code

#pragma mark - Table view data source
- (void)viewDidLoad{
    // the following is for example only.  You'll probably never instantiate a UITableView this way
    UITableView *tableView = [[UITableView alloc] init];
    tableView.delegate = self;
    tableView.dataSource = self;
    [super viewDidLoad];
}
 
# pragma mark UITableView DataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}
 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [myArray count];
}
 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
 
    NSDictionary *current = [myArray objectAtIndex:indexPath.row];
    // Configure the cell...
    cell.textLabel.text = [current objectForKey:@"name"];
 
    UILabel *captionLabel = (UILabel *)[loadedCell viewWithTag:2];
    captionLabel.text = [current objectForKey:@"caption"];
 
    UIImageView *imageView = (UIImageView *)[loadedCell viewWithTag:3];
    imageView.image = [UIImage imageNamed:@"comment_minus_48.png"];
 
    return cell;
}
 
#pragma mark - Table view delegate
 
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    MyDetailViewController *controller = [[MyDetailViewController alloc] init];
    [self.navigationController pushViewController:detailViewController animated:YES];
    [detailViewController release];
}

This is the very least you have to do.  To create a highly stylized table view requires much more.

 

Enter Block Programming

Since iOS 4, the delegate pattern has been undermined by the introduction of block programming. Since then the engineers at Apple have been incrementally adding block support to many of the SDK’s frameworks and classes.

One area that has yet to benefit from the wonder of blocks is the table views above. Table views are quite possibly the most ubiquitous element in iOS programming and are still extremely verbose and tedious to create. The code above feels disjointed and becomes difficult to maintain over time. To reconcile this I’ve started an open-source project to make building table views a snap.

Konstructor enables a refreshing and unique way to create table views in iOS that’s more declarative.  Here’s an example of building a table view the Konstructor way:

View simpler code using Konstructor

self.tableCellHeight = 100.0; // set the height for each cell
self.customCellNibName = @"YourNibName"; // will default to KonstructorTableViewCell
 
/* This is where blocks come in.  The part starting with <strong>^</strong> marks the block */
[self addRowsFromArray:items withBuilder:^(id item, TableRowBuilder *builder){
    NSDictionary *current = (NSDictionary *)item;
    /* Fully customize the cell */
    builder.configurationBlock = ^(UITableViewCell *cell){
        UILabel *titleLabel = (UILabel *)[loadedCell viewWithTag:1];
        titleLabel.text = [current objectForKey:@"name"];
        UILabel *captionLabel = (UILabel *)[loadedCell viewWithTag:builder.captionTag];
        captionLabel.text = [current objectForKey:@"caption"];
        UIImageView *imageView = (UIImageView *)[loadedCell viewWithTag:builder.iconTag];
        imageView.image = [UIImage imageNamed:builder.selected ? @"comment_plus_48.png" : @"comment_minus_48.png"];
    };
}];

 

This one block of code does everything (and more) than the previous example. The fact that all this configuration code is in one place makes the code more readable and easier to maintain.

If you want to check it out you can clone and fork the code on github.