Nicole: “We’re back, and I just got Zach out of the car seat, and as I was getting him out, he raised his hands up and said “up”! And then I said, “Wow, did you just say ‘up’?” And he said “Up!” again.”
Monthly Archives: June 2010
Zach 2010-06-09
The quest for a better UIAlertView
One of the things that has annoyed me while developing my iPhone game “Wordly” are dialogs that appear modal to the user, but are non-blocking from the programmer perspective. For example, let’s take UIAlertView
.
You tell a UIAlertView
to show itself and the user sees a modal dialog, but the code after your show
message keeps executing, before the user even clicks anything. The way to find out which button the user clicked is via a callback; the UIAlertView
calls the alertView:clickedButtonAtIndex:
method of the delegate object (an object that conforms to the UIAlertViewDelegate
protocol) that you supply.
So using the calling object as the delegate, it looks something like this:
A few things bother me about this style:
- Displaying a modal dialog and then reacting to the choice is conceptually a simple, sequential process, but you end up splitting your steps between two methods. The first method doesn’t even mention the name of the second method, so for programmers who are unfamiliar with Cocoa or just forgetful of what the magic method is in
UIAlertViewDelegate
, it’s not immediately clear how the code flows. - To decide how to handle a button press, you have to match against a button index or a button title that you used in the other method. This is in my mind a violation of the DRY principle and it’s error prone.
- If your class is the delegate for a bunch of dialogs, stuff starts to get messy pretty quickly, as your method needs to distinguish between different dialogs by looking at the alert view’s tag or otherwise inspecting it.
Basically, it’s not as readable as I would like. It seems I am not alone:
- http://discussions.apple.com/message.jspa?messageID=9579445
- http://osmorphis.blogspot.com/2009/10/truly-modal-uialertview.html
- http://www.box-of-monkeys.co.uk/index.php?id=31&tp=2
Interestingly, the authors of the latter two blog posts also develop solutions that are similar to my first solution below. I’ve not yet found anything that looks like the second solution that I discuss below.
My first idea for how to make things more intuitive was to create a new class called ModalAlertView
. Basically it just polls in a while loop, until the callback gets called. NSRunLoop
‘s runUntilDate
method is used in the while loop to let the event loop process events – here’s the relevant part of the code:
Now you can use this modal dialog something like this:
This seems to work pretty well, but it still bothers me. Polling is wasteful and we’re talking about mobile devices here, so we’re wasting processor time and battery life and when we have multitasking in iPhone OS 4, this will be wasting time that other processes could be using. The API also seems to really be pushing the developer in the direction of having non-blocking code and this approach kind of subverts that. I’d rather not go against the grain.
So I searched for another solution. For a while I thought the problem I was trying to solve was how to create a modal dialog. But then it dawned on me that the real problem was that I wanted a more intuitive way to create and react to dialogs. Making the dialog modal was one way to make things more intuitive to my sequential brain, but there was perhaps another way.
The other way was to create a class that displays the dialog and then acts as the delegate for that dialog, doing dispatching to whatever methods the caller specifies for the buttons, thereby relieving the caller of the responsibility of doing the dispatching. The caller uses the new API like this:
Concise. Simple. And it can be implemented with pretty simple Objective-C, without funky polling and run loops. Here’s what the implementation looks like:
Nothing too hairy in there, that I can see.
It gives you a simple API that lets you create buttons and link them to specific handler methods. You don’t even need to worry about releasing the dialog object as it adds itself to the autorelease pool after the callback fires.
Objective-C afficionados, please send me any suggested improvements…
Cocoa folks: How would you indent this code?
One of the things that has bugged me about Cocoa is that the long method names and the de-facto indentation style (of lining up the colons in method invocations) conspire to create hard-to-read code with super long lines and sometimes weird indentation from Xcode.
For an example, see this little snippet of Objective-C:
Two problems:
- Some of the lines are really long and they wrap in a reasonable size window on my 15″ laptop screen.
- The indentation gets funky – e.g.: the “Do this other cool thing” button.
I don’t know how to make this code look good beyond doing uglyish things like doing the assignment separately from the type declaration or creating the button arguments beforehand and assigning them to variables. I hate to do something just to make the formatting look nice, although I’m tempted, because I don’t like the way this code looks.
How would you format this?