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.