How To Use Blocks in iOS 5 Tutorial – Part 2

This is a blog post by iOS Tutorial Team member Adam Burkepile, a full-time Software Consultant and independent iOS developer. Check out his latest app Pocket No Agenda, or follow him on Twitter. Welcome back to our tutorial series on using blocks in iOS 5 – with some Storyboard/Interface Builder practice along the way! In […] By .

Leave a rating/review
Save for later
Share

This is a blog post by iOS Tutorial Team member Adam Burkepile, a full-time Software Consultant and independent iOS developer. Check out his latest app Pocket No Agenda, or follow him on Twitter.

Welcome back to our tutorial series on using blocks in iOS 5 – with some Storyboard/Interface Builder practice along the way!

In the first part of the series, we used iOS 5.0 Storyboards to set up the view and wound up with a nice-looking interface, close to what you see to the right.

In this second and final part of the series, we finally get to blocks! We’ll talk about what blocks are, how their syntax works, how you use them, and cover tons of examples.

We’ll show you how you can use blocks with NSArrays, for UIView animations, Grand Central Dispatch, and much more!

So unblock your schedule and keep reading for some blocks practice and fun!

Getting Started: An Intro to Blocks

Blocks are a new feature that was introduced in iOS 4.0 and Mac OSX 10.6. Blocks can greatly simplify code. They can help you reduce code, reduce dependency on delegates, and write cleaner, more readable code.

Even so, Blocks are a feature that remains unused by some developers who may not totally grasp how to use them. But they are definitely a tool that you, as an Objective-C programmer, will want to have in you toolbox and know how to use.

Let’s look at the “Who, What, Where, Why, and When” of Blocks.

What Are These ‘Block’ Things and Why Are They So Important?

Why do I need these fancy block things?

Why do I need these fancy block things?

At its core, a Block is a chunk of code that can be executed at some future time.

Blocks are first-class functions, which is a fancy way of saying that Blocks are regular Objective-C objects. Since they’re objects, they can be passed as parameters, returned from methods and functions, and assigned to variables.

Blocks are called closures in other languages such as Python, Ruby and Lisp, because they encapsulate state when they are declared. A block creates a const copy of any local variable that is referenced inside of its scope.

Before blocks, whenever you wanted to call some code and have it call you back later, you would typically use delegates or NSNotificationCenter. That worked fine, except it spreads your code all over – you start a task in one spot, and handle the result in another.

Blocks are nice because they keep your code related to handling a task all in one place, as you’ll see soon.

Who Are Blocks For?

YOU! Blocks are for everyone! Seriously though, Blocks are for everyone and everyone WILL use Blocks. Blocks are the future, so you might as well learn them now. Many built-in framework methods are being rewritten or augmented with Block-based versions of existing functionality.

How Do You Use Blocks?

This nifty image, via the iOS Developer Library, does a good job explaining Blocks syntax:

The declaration format for Blocks is as follows:

return_type (^block_name)(param_type, param_type, ...)

If you’ve programmed in any other C-type language, this should look pretty familiar to you, except for that ^ symbol. The ^ symbol is what denotes “this thing we are declaring is a block.”

If you can get your head around the idea that ^ means “I’m a block”, congrats – you’ve just learned the hardest thing about using blocks! ;]

Note that parameter names are not required at this point, but you can include them if you’d like.

Here’s an example declaration of a block:

int (^add)(int,int)

Next, here’s a block definition:

// Block Definition
^return_type(param_type param_name, param_type param_name, ...) { ... return return_type; }

This is how the Block is actually created. Notice that this has a different structure than the Block declaration. It begins with the ^ symbol and is followed by the parameters, which must be named at this point, and must match the type and order of the parameter list of the Block declaration to which it’s assigned. This is followed by the actual code.

When you define Blocks, the return type is optional and can be inferred from the return type in the code. If there are multiple return statements, they must all be of the same type (or cast to the same type).

Here’s an example of a Block definition:

^(int number1, int number2){ return number1+number2 }

If we put the Block declaration and definition example together, we get a full statement:

int (^add)(int,int) = ^(int number1, int number2){ 
                            return number1+number2;
}

And we can use the Block like so:

int resultFromBlock = add(2,2);

Let’s look at a couple of examples of using Blocks vs the same code written without Blocks.

Example: NSArray

Lets look at how Blocks change how we might do some operations on an array.

First let’s look at a normal for loop:

BOOL stop;
for (int i = 0 ; i < [theArray count] ; i++) {
    NSLog(@"The object at index %d is %@",i,[theArray objectAtIndex:i]);
    if (stop)
        break;
}

The "stop" variable in the above method might not make much sense to you. But it will become clearer when you look at the Block-based approach for the same method. The Blocks approach provides for a "stop" variable which allows you to stop the loop processing at any point and we're simply duplicating that functionality here to provide equivalent code to the Blocks-based approach.

Now let's look at the same code as above using fast-enumeration:

BOOL stop;
int idx = 0;
for (id obj in theArray) {
    NSLog(@"The object at index %d is %@",idx,obj);
    if (stop)
        break;
    idx++;
}

And now with Blocks:

[theArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
    NSLog(@"The object at index %d is %@",idx,obj);
}];

In the Block-specific code above, you might wonder what the "stop" variabl is. This is simply a variable that can be set to YES from within the block to stop further processing. This parameter is specified as part of the block to be used by the enumerateObjectsUsingBlock method.

The above is a pretty trivial example and it might be admittedly difficult to see the advantage of Blocks in this case. But there are two things I want to point out about the Blocks approach:

  1. Simplicity. Using Blocks, we have access to the object, the object index in the array, and a stop variable, all without having to write any code. This means less code, which means less chance of a coding error (not that we make any coding errors).
  2. Speed. There might be a slight speed advantage to using the Block method over the fast-enumeration method. This (possible) speed advantage is so minute in this case it is barely worth mentioning, but in more complex cases, the advantage becomes significant. (Source)

Example: UIView Animation

Let's take a simple animation that operates on a single UIView. It changes the view's alpha to 0 and moves the view down and to the right 50 points by 50 points, then removes the UIView from the superview. Easy, right?

The Non-Block approach:

- (void)removeAnimationView:(id)sender {
    [animatingView removeFromSuperview];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    [UIView beginAnimations:@"Example" context:nil];
    [UIView setAnimationDuration:5.0];
    [UIView setAnimationDidStopSelector:@selector(removeAnimationView)];
    [animatingView setAlpha:0];
    [animatingView setCenter:CGPointMake(animatingView.center.x+50.0, 
                                         animatingView.center.y+50.0)];
    [UIView commitAnimations];
}

The Block approach:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    [UIView animateWithDuration:5.0 
                     animations:^{
                        [animatingView setAlpha:0];
                        [animatingView setCenter:CGPointMake(animatingView.center.x+50.0, 
                                                             animatingView.center.y+50.0)];
                     } 
                     completion:^(BOOL finished) {
                         [animatingView removeFromSuperview];
                     }];
}

If we look at these two methods, there are three advantages that stand out to me:

  1. Simplifies code. With blocks, we don't have to do things like declare an entirely separate method for completion callback, or call the beginAnimations/commitAnimations lines.
  2. Keeps code together. With blocks, we don't have to start the animation in one place, and have a callback method in another place. All of our code relating to animations is in one spot, which makes it easier to read and write.
  3. Apple says so. This is an instance of Apple having used Blocks to rewrite functionality that existed prior to Blocks, and now the official Apple recommendation is to transition over to the Block-based method, if possible. (Source)

When Do You Use Blocks?

I think that the best advice that can be given here is to use Blocks when they are most appropriate. There might be times that you want to continue using old methods either because you want to maintain backwards compatibility or because you are more familiar with the older way of doing things. But each time you come to such a decision point, think whether Blocks would simplify your life and whether you can substitute a Blocks-based method instead. Then do what works best for you.

Of course, you might find yourself needing to use Blocks more and more in the future simply because many frameworks, both third-party and Apple's own, are being written and re-written to use Blocks. So start using Blocks now so that you're armed to face the future.