Pretty image
Three unsung developer features of iOS 4 will make your life easier and change your code dramatically: blocks, gestures, and properties without ivars.

Apple has released iOS 4, the latest version of its mobile operating system, and by now you’ve heard over and over that iOS 4 has multitasking. You’ve also heard about iAds and a handful of other features that Apple is focusing their message on. But there are three unsung developer features of iOS 4 that will make your life easier and change your code dramatically: blocks, gestures, and properties without ivars. All of these are new for iPhone developers. The first was introduced with Mac OS X Snow Leopard, the second with the iPad release, and the third is the result of a change in the iPhone simulator.

iVar-Free Properties

Properties without iVars? That may sound like a minor change, but it’s really freeing. Let me show you what I mean.

I’ve created a simple view-based project for iPhone 4 and named it “MoveMe.” I’ve set the view’s background color to be black and added an image view at the top left of the screen containing a PNG of last month’s PragPub cover.

image1.jpg

We’re going to animate a few properties of the view and the image view, so we need an outlet for the image view. Here’s how you would have added the property in the old days. You would have declared an instance variable and the corresponding property in the view controller’s header file like this:

 #import <UIKit/UIKit.h>
 @interface MoveMeViewController : UIViewController {
  UIImageView *imageView;
 }
 @property(nonatomic, retain) IBOutlet UIImageView *imageView;
 @end

All that’s left is to synthesize the property in the implementation file and connect the outlet in the nib and you’re off and running. You can communicate with the image view and move it around the screen, change its opacity, etc.

One advantage in the Xcode 3.2.3 release that accompanied the iPhone 4 SDK release is that we now have a simulator built on the modern runtime. The result is that we can declare the property without specifying the underlying ivar, like this:

 #import <UIKit/UIKit.h>
 @interface MoveMeViewController : UIViewController {
 }
 @property(nonatomic, retain) IBOutlet UIImageView *imageView;
 @end

The runtime will synthesize the instance variable for you. You should, however, take care to address the property and not the underlying variable. In other words, for the most part you should use self.imageView and not imageView to send messages to the image view.

It turns out that you could always do this for iPhone development if you were only running your apps on the device. This feature was not available on the simulator until this most recent release. Feel free to leave out the backing ivars even if you are targeting iPhone 3.1.3 or below so long as you are using the latest simulator.

If you use the latest release of LLVM for development you can also configure your project to synthesize your properties by default. In other words you won’t even have to include the @synthesize to get the compiler to generate your getter and setter in the implementation file. There is currently a bug in LLVM that prevents you from addressing the synthesized variables (which you need to do, for instance, in the dealloc), but a fix is on its way.

Gestures

For the next step in our little animation project, let’s look at gestures. Eric Freeman, my co-author on our iPad book wrote a great chapter on Gestures. The same APIs introduced for the iPad are now available on the iPhone.

Imagine you wanted to implement a horizontal swipe before the new Gesture APIs were introduced. You would have had to implement the delegate methods touchesBegan:withEvent: and touchesEnded:withEvent. You’d then have had to check that the user moved their finger enough to the right or to the left and not too much up or down so that it truly was a swipe. There was no standard way of doing this, so a swipe in my app and a swipe in your app might be completely different motions.

One benefit of the new Gesture APIs is that Apple has standardized what these common gestures feel like to the end user in all apps. This brings a uniformity to the user experience on the iPhone. A second benefit is that it is much easier to respond to a swipe. Here’s how we’d create and register a swipe to the right:

 -(void) registerSwipeToTheRight {
  UISwipeGestureRecognizer *rightSwipeRecognizer =
  [[UISwipeGestureRecognizer alloc]
  initWithTarget:self
  action:@selector(userDidSwipeRight)];
  rightSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
  [self.view addGestureRecognizer:rightSwipeRecognizer];
 }

This creates a swipe gesture recognizer that will call the method named userDidSwipeRight. We configure it to respond only to horizontal swipes to the right and add it to the view. Next let’s look at what sort of animation you might add when the user swipes right.

Blocks

We’ll take advantage of blocks when we implement the animation in our project. Apple is introducing blocks almost everywhere they can. We saw this last year with the Snow Leopard APIs, and this year the iPhone 4 APIs are following suit. I’ve written an entire chapter on blocks in my Cocoa programming book but I’d like to show you a simple example of how you might use them.

Suppose when the user swipes to the right we perform the following animation. Let’s take two seconds to change the view’s background color from black to white and move the cover down to the bottom right corner in the userDidSwipeRight method:

 -(void) userDidSwipeRight {
  [UIView beginAnimations:@"swipe right" context:nil];
  [UIView setAnimationDuration:2];
  self.view.backgroundColor = [UIColor whiteColor];
  self.imageView.frame = CGRectMake(220, 320, 115, 146);
  [UIView commitAnimations];
 }

This is a pretty familiar-looking animation. The animation consists of two actions: changing the view’s background color to white and changing the image view’s position to the bottom right corner of the screen. We set the animation to last for two seconds and then we enclose it all in between beginAnimations and commitAnimations.

I’m not going to explain blocks at all—I just want to show you this example and hopefully you’ll think “wow, that’s cool” and head off to learn some more about blocks. With blocks, the previous animation is implemented like this:

 -(void) userDidSwipeRight {
  [UIView animateWithDuration:2
  animations:^{
  self.view.backgroundColor = [UIColor whiteColor];
  self.imageView.frame = CGRectMake(220, 320, 115, 146);
  }];
 }

This time we use the animateWithDuration:animations method and we pass in a block as the second argument (the ^ signifies the beginning of the block). All that is to be animated is contained between the curly braces. Look back and forth between the two versions of the animation and I think you’ll begin to see how blocks turns some of your traditional coding patterns on their head.

You can get a lot fancier. Suppose, for example, you want to chain two animations together. Use the animateWithDuration:animations:completion method and put the second animation in the completion block. You can continue the pattern and chain as many animations together as you like. Here I’ve faded the cover image as I’ve moved it and then set the alpha back to one when the first animation is complete:

 -(void) userDidSwipeRight {
  [UIView animateWithDuration:2
  animations:^{
  self.view.backgroundColor = [UIColor whiteColor];
  self.imageView.frame = CGRectMake(220, 320, 115, 146);
  self.imageView.alpha = .3;
  }
  completion:^(BOOL finished){
  [UIView animateWithDuration:2
  animations:^{
  self.imageView.alpha = 1;}];
  }];
 }

If you’re not familiar with blocks, they will look odd at first. But take the time to get familiar with blocks, as Apple has added methods all over the Cocoa frameworks that are built to handle blocks. You’ll pass blocks off to collections to sort them or perform the same operation on the various elements. You’ll use blocks with Game Center and iAds, and familiar APIs such as the animation methods we’ve looked at here now have variants that can take blocks.

I’ve used this simple example to show you how to drop the ivars that back your properties, how to use the new gesture recognizers, and how to begin the path of embracing blocks. Enjoy.

Daniel is a podcaster, author, coder, and trainer at dimsumthinking.com. He is the co-author of the Prags’ iPad book and author of the book on Cocoa programming. He teaches iPhone and Cocoa programming for the Pragmatic Studios. Mostly he loves hanging out in the kitchen or the back yard with his wife and daughter.

Send the author your feedback or discuss the article in the magazine forum.