We're hiring!

We're actively seeking designers and developers for our all three of our locations.

Migrating to Closures in Objective C

Apple introduced closure support with the release of Snow Leopard. Plausible Labs has since created a framework and a drop-in runtime that provides closure support for both MacOS X 10.5 and the iPhone SDK. Closure support is a fundamental and important change to the Objective-C language. Functions are now first-class citizens in the runtime environment; they can be saved, copied, and passed around just like any other object.

That being said, much of the existing API in both MacOS X and the iPhone SDK rely on callbacks, selectors, and delegate patterns to cope with lack of first-class functions. But don’t let that stop you from using closures. It is relatively easy to create small intermediary wrappers that bridge the gap between callbacks and closures.

Lets use a common scenario that most iPhone developers come across while developing an application—showing an alert dialog. The UIAlertView is how an iPhone application can provide or ask for feedback from the user. In order to know when the alert has been dismissed and what button has been clicked an object is required to implement part of the UIAlertViewDelegate protocol.

As an example, lets pretend we want a generic confirmation alert:

This confirmation alert object wraps the creation of the alert and expects that the user of the object will provide a confirmation message and delegate to handle the dismissal of the alert. The delegate will have to implement part of the UIAlertViewDelegate protocol and then handle the confirmation by checking the the button indexes. Adding to the complexity, what if the delegate object is dealing more than one alert?

In order to manage a couple of relatively simple alert views we have to maintain state and add branching complexity in our delegate callback. The code is disjoint and its intent is being clouded by trying to manage the alerts and the state of various variables.

Refactoring this code to use closures can solve the imperative problem of branching and maintaining internal state. A closure is bound to its lexical environment, which means that we do not need to maintain variable state across two different methods. Additionally, a closure is an object so we can make it responsible for handling an individual alert—rather than having one object maintain multiple alerts.

First, we should define the interface of the block we’ll want to use:

Next, we need to redefine and refactor the show method on the ConfimationAlert:

The ConfirmationAlert has been changed to accept two blocks, one for handling a confirmation click and the other for a cancellation click. The delegate method has been refactored into the ConfirmationAlert where it looks up the alert view and invokes the appropriate block. This will significantly reduce the complexity of the object using the ConfirmationAlert. The object no longer has to maintain state, branch unnecessarily, or create a delegate handle.

The code associated with this demo can be found here. For more information on closures in Objective-C be sure to read Mike Ash’s series on closures (Part 1 and Part 2).

Justin DeWind (45 Posts)

This entry was posted in Objective-C and tagged , . Bookmark the permalink. Both comments and trackbacks are currently closed.

4 Comments

  1. Posted April 7, 2010 at 5:35 pm

    Hey,

    interesting ideas, thanks for sharing them.

    Personally I’m not a huge fan of methods that take multiple block objects and ferreting away all that extra context in statics feels a bit kludgy.

    I’m not sure how you feel about using the UIAlertView’s layer to store context but here’s a rough outline of how it would look structured that way:

    http://gist.github.com/359426

    Note that I haven’t even tried to compile that – it’s just for the general idea of it.

    Regards, Trev

  2. Posted April 7, 2010 at 5:35 pm

    Trevor,

    The implementation details and the particular strategy used is always up for discussion. Creating a managed wrapper delegate is another strategy I have used, like yourself.

  3. John C. Randolph
    Posted April 7, 2010 at 5:35 pm

    Blocks, not closures. This is Objective-C we’re talking about, not LISP.

    -jcr

  4. mr f
    Posted April 7, 2010 at 5:35 pm

    There is a discussion about whether these things are true closures or not in the comments of Mike Ash’s blog post here: http://www.mikeash.com/pyblog/friday-qa-2008-12-26.html

    The discussion appears inconclusive.