Kotan Code 枯淡コード

In search of simple, elegant code

Menu Close

How iOS SDK 4 Makes Life Easier

With the release of the iOS SDK 4, Apple has included a whole bunch of things that make developers happy and make their lives easier. These features aren’t as shiny or as eye-catching as some of the stuff that comes with the iPhone 4 (not to be confused with SDK 4… that is an important distinction!), but they are, in my opinion, some of the most useful enhancements to hit the iPhone SDK since the very beginning.

Some of the ones I’ll talk about in this post are: Blocks, “no ivar” Properties, Gesture Recognition, and Deployment.

Blocks

If there was a single barrier at the foot of which one could lay blame for preventing developers from learning and adopting new platforms, it would no doubt be terminology. The worst is when two platforms use the same word to mean two entirely different things. C# developers can think of blocks as if they were lambdas or actually more specifically, delegates. The problem here is in the Apple world, a delegate isn’t a function pointer like it is in C#, it’s actually an object that conforms to a protocol typically used to supply data and/or views to another component.

In case you haven’t been programming for the iPhone or for the Mac for long, the single most commonly used pattern for asynchronous anything is you create an instance of the helper object, configure it, set it’s delegate to the calling object, and then tell it to go do it’s work.

So, for example, if you want to parse an XML document, you create an instance of the NSXMLParser class. Once you’ve got this, you tell it to go munch on some data in order to do the parsing. In the Apple world of delegates, every time the parser does something meaningful, it will invoke a method on the delegate. So, every time the parser starts an element, ends an element, encounters an error, reads a blob of data – all of these invoke methods on the delegate.

This is a great pattern and has worked for centuries (ok, maybe not centuries, but you get the idea). The problem shows up when you need to perform a bunch of asynchronous operations. What happens if you want to parse two XML documents. Now, if the delegate is the same object, you’re stuck littering your code with awful if statements used to detect which active parse operation invoked the delegate method. It gets ugly…fast.

Enter blocks. Blocks are more familiar to the way functional programmers do things and the way C# programmers who have embraced LINQ, lambdas, and semi-functional programming think. Blocks showed up at the WWDC when Apple previewed Snow Leopard and its new multi-tasking infrastructure: Grand Central Dispatch (GCD). Turns out these things are handy for more than just splitting tasks across multiple cores. Turns out blocks aren’t just handy, they’re awesome, and they dramatically simplify not only your source code (no more “delegate spaghetti”) but also just make you feel all warm and fuzzy inside.

Let’s say you want to animate a view but you want to change more than one property during the animation. You could do this the old (ugly) way, or you can do it the new (awesome) way:

- (void)doAwesomeMovement {
    [UIView animateWithDuration:4
       animations:^{
           self.coolView.frame =
              CGRectMake(100, 100, 140, 240);
           self.coolView.alpha= 1.0;
       }];
}

This is just the tip of the iceberg. Simple animations are just that, simple. Looking at the Block above, you’re probably thinking that it doesn’t look all that different from using callbacks and delegates. You’re right, but what if you want to do something when you finish? Time and time again, I see my own code fail because I try to get or set some model property while an animation is still taking place and I have to step back, make another delegate, and wait for the “finished” callback. The problem is the finished callback and the work being done during the animation are never near each other, so it makes my code difficult to read. You can use another block version of the animateWithDuration:… method like this one, which will fade the view to half-transparent while moving it to it’s new location, then snap it’s opacity back to solid when it finishes.

- (void)doAwesomeMovement {
    [UIView animateWithDuration:4
       animations:^{
           self.coolView.frame =
              CGRectMake(100, 100, 140, 240);
           self.coolView.alpha= 0.5;
       }
       completion:^(BOOL finished){
           self.coolView.alpha= 1.0;
           [self.soldier signalReportingForDutyBoss];
       }
    ];
}

There are some other new APIs that are covered under an NDA that also make extensive use of blocks. In short, if you’re building your apps with Xcode 3.2.3 and the 4.0 SDK, you should be using blocks. Not just because they’re new and shiny, but because they simplify your code, make your code easier to read, and make it easier to debug.

Gesture Recognition

In the beginning, we had methods like touchesBegan: and touchesEnded: and touchesMoved:. Back in the day, us developers had to code these methods uphill both ways in the snow. We had access to the absolute lowest levels of information. We could figure out when a finger touched the screen, when it left the screen, and if it moved between the two events. This was fine for just dealing with taps and actually made for a fairly easy drag-and-drop implementation (though we had to do some ugly stuff to keep the dragged item from twitching and jerking).

If you wanted to do anything else, you had to do it by hand. Detecting things like pinches, swipes, wipes, pokes, prods, and any other kind of gesture all came down to you, the developer. Sure, we could do it ourselves but our hand-coding of the timing between events for detection always seemed “off” somehow compared to the standardized way Apple’s software detected the core suite of gestures.

Now we have been given gesture recognizers. Apple has thankfully given us pre-defined code that detects all of the various types of standard gestures and we can add these recognizers to our views with a single line of code:

[self.view addGestureRecognizer:myDoubleTapRecognizer];

To create an instance of these gesture recognizers, just run them through the standard alloc/init pair:

UITapGestureRecognizer myDoubleTapRecognizer =
  [[UITapGestureRecognizer alloc] initWithTarget:self
  action:@selector(userDoubleTapped)];
myDoubleTapRecognizer.numberOfTapsRequired = 2;

Now the developer no longer has to bear the burden of figuring out how many milliseconds between taps or keeping an eye on the number of fingers used so that a double-finger double-tap won’t trigger the single-finger double-tap. Additionally, multiple gesture recognizers can be added to a view AND gesture recognizers can be combined to create events that only occur during simultaneous gestures.

Properties

This one isn’t quite as big as the other two, but is still downright handy. In the olden days, back before electricity, fire, and Xcode 3.2.3, we had to manually create our own ivars. For you C# programmers, that basically means that every property had to have an explicitly created member variable (ivar). In C#, since version 3.0, we’ve been able to create “automatic properties”, where the compiler created the underlying member property to backfill the property data. Now, the iPhone has this as well.

Now we don’t need that. Now we can create properties that don’t need ivars:

@property(nonatomic, retain) SGSoldier *gamePawn;

And when we synthesize that property, the underlying ivar is created for us automatically.

Deployment

I’ve already done a blog post detailing the benefits of deployment using Xcode 3.2.3, but the key words to remember here are automatic provisioning. Gone are the days when worrying about keys and security and provisioning profiles kept you from deploying your app to a test device or prevented another team member from deploying checked-in source code to his test device. This is huge, huge, huge and has dramatically changed my stress level while coding.

And so, in summary, I just want to say that the iOS 4.0 SDK is an absolutely fantastic enhancement over the previous and the combination of blocks, ivar-less properties, incredibly easy gesture recognition, and automatic provisioning have re-ignited my joy for making iPhone applications.