Objective-C Blocks in iOS 4.0

The foursquare 3.0 application for iOS is a major release for us, and marks the maturation of several major technical efforts. With so many new features in the works, we decided that it was time to make the leap to iOS 4.0 in order to better take advantage of the platform. Since less than 5% of our iPhone API calls are coming from iOS 3.x devices, we felt that the move would not be too painful for our users. Even so, increasing platform requirements warranted serious consideration.

The single most compelling reason for the upgrade is the addition of a new language feature called blocks. Known more traditionally as closures (almost synonymous with inner/anonymous/lambda functions), blocks allow the programmer to succinctly define an operation that encapsulates both actions and data. Closures are by no means a new concept, and have played a key role in the history of functional languages. Despite this, blocks were only added to Objective-C with the release of Mac OS X 10.6 in 2009.

Since Objective-C is an object-oriented language, it already supports a standard mechanism for encapsulating functions and data: the class. Anywhere that a programmer might use a closure, a class instance could suffice. For example, the standard callback pattern in Cocoa takes a function pointer, and a second context pointer of type id or void, through which any relevant data is passed. The new pattern takes a single block argument, which serves as both callback function and contextual data. Many debates have weighed the merits of objects versus closures; the bottom line is that these constructs are similar tools, originating from different traditions of language design.

One of the most thought-provoking comments I ever heard at WWDC came from a seriously bearded Apple compiler guru, during the question and answer session of a compiler talk: “We finally have closures in C!” The presentation had already made clear that the implementation of blocks in GCC was no simple task, but that comment (and particularly his word choice) made me think hard about why blocks are so valuable.

One reason is brevity. Object-oriented programming can be very verbose, and blocks allow programmers to define small pieces of logic flexibly, inline, and in a consistent manner. The growing popularity of dynamic scripting languages has demonstrated that the concise, flexible nature of functional programming need not be reserved for ‘academic’ languages. But why does brevity matter? Is it simply a stylistic concern?

Objective-C is a verbose language. Method names tend to be long but easy to read, because arguments are essentially labeled in every call. Less helpful is the boilerplate @ syntax required to define Objective-C classes. As a Cocoa programmer, I find myself more reluctant to write small, organized classes than when I work in C++ or Python. Blocks elegantly address the common case where we need to pass some structured data along with a callback, but don’t really need the formal class definition because we are only using the callback in one place. With blocks, the code becomes simpler, consolidated, and easier to update.

Take for example this simple iOS 3.x (pre-blocks) animation code from a view controller:

- (void)animateFadeOut {
    [UIView beginAnimations:@"fadeOut" context:nil];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(fadeOutDidStop:finished:context:)];
    [UIView setAnimationDuration:0.3];
    self.loadingView.alpha = 0.0;
    [UIView commitAnimations];
}

- (void)fadeOutDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
    [self.loadingView stopAnimating];
    [self.loadingView removeFromSuperview];
}

With blocks, the preferred pattern becomes:

- (void)animateFadeOut {
    [UIView animateWithDuration:0.3
                     animations:^{ self.loadingView.alpha = 0.0; }
                     completion:^(BOOL finished) {
                         [self.loadingView stopAnimating];
                         [self.loadingView removeFromSuperview];
                     }];
}

The callback disappears, and the entire operation now appears in one line. Notice also how the new method does away with the need for a number of calls to UIView. Fairly trivial, but now imagine that the callback needs to perform a more complex action. For example, suppose we have several objects loading, and on completion of any given object, want to perform two actions: remove the appropriate loading graphic, and enable a button.

In 3.x, we would need to pass a context containing pointers to the relevant views, contained in either a dictionary or some other container instance. Suddenly, focus has shifted to defining and constructing the context. In 4.0, on the other hand, we simply reference the objects in question inside the block, thereby defining the ‘context’:

- (void)animateFadeOutWithLoadingView:(UIView *)currentLoadingView button:(UIButton *)currentButton {
    [UIView animateWithDuration:0.3
                     animations:^{ self.loadingView.alpha = 0.0; }
                     completion:^(BOOL finished) {
                         [currentLoadingView stopAnimating];
                         [currentLoadingView removeFromSuperview];
                         currentButton.enabled = YES;
                     }];
}

The beauty of this example is that we need not worry about any retain/release semantics that might complicate the lifetime of a 3.x-style context. Instead, the block ‘closes over’ all the variables that it references, and the run-time retains them as necessary. When the application completes the animation, it disposes of the block, and the references it contains. This ‘lexical scoping’ is what makes closures so useful.

For problems with more complex memory semantics, the clarity that blocks offer becomes a substantial benefit. The feature was announced in conjunction with Grand Central Dispatch, Apple’s general purpose concurrency framework, and it is in this realm that blocks really shine. Writing safe, asynchronous code is difficult, in part because tracking the state of each context in flight can become a major bookkeeping effort. The simplicity and ad-hoc encapsulation that blocks provide will aid tremendously as we move into the era of multicore mobile computing.

In addition to blocks, iOS 4.0 offers several other features that improve the brevity of code. The redundancy of instance variables and properties is fading away, and class extensions can now declare private members. Regular expressions, long absent from Cocoa, have finally surfaced, replacing NSScanner for many tasks. The trend towards more dynamic patterns continues, and I can’t help but wonder how long it will be before garbage collection and MacRuby make the leap from the Macbook to the iPhone. In any case, we hope that you enjoy the new release, and look forward to improving the foursquare experience even more on iOS 4!

- George King, iOS Engineer

@georgewking