iOS Programming Recipe 25: Implementing Blocks Part I

Every now and then new stuff comes along that makes our lives easier. One of the best things to come to Objective-C is the advent of blocks. Blocks can simplify callbacks, enumeration, and they have huge benefits in terms of multi-threading. At first, blocks will blow your mind. Block syntax is weird, but once you get the hang of em’ they’re actually kinda easy.

Assumptions

  • You have a fairly good grasp on creating classes, methods, and other general Objective-C tasks.

So What is a Block?

A block is a magical being in some kind of limbo between C and Objective-C. You can add a block to a dictionary or an array and You can pass a block around in methods, but you wouldn’t send a message to a block. You CAN send a message to a block, but it won’t respond. The structure of a block is more like a C function, but they can be called inline with a method. Confused yet? Hang in there we’re just getting started.

Declaring and Using Blocks

Here we have a variable that points to an object with an NSString type

NSString *string;

Nothing new here, I’m sure by now you’ve seen it at least a dozen times. Now compare it to a simple block decleration:

NSInteger (^mathOperation)(NSInteger, NSInteger);

This is a little bit different. The pointer to a block is designated as ^ (caret) instead of * which is a pointer to an object. After the ^, we define the block name (variable name) and the arguments the block takes as input. This block structure takes two NSIntegers and returns one NSInteger. The type we should receive will be an NSInteger. the variable name is “mathOperation”. I know, this last bit is totally not obvious and don’t ask me why the ^ goes inside the parenthesis.

Note: Although I called the caret a pointer to a block, It’s not technically correct. Blocks are stack objects when defined and therefore exist on the stack much like an int or a float. For the sake of comparison I called a block variable pointer, but you should probably think of it more as a reference.

Now that we know how to declare blocks, lets move on.

Again, For comparison, the NSString could be defined using a literal like so:


1
NSString *string = @"Blocks Are Awesome";

The Block has some funky syntax associated with defining it, so here’s what that looks like:


1
2
3
4
5
NSInteger (^mathOperation)(NSInteger x, NSInteger y) = ^NSInteger(NSInteger x,NSInteger y){

return x + y;

};

Before we created a block variable, now we’re actually creating the block that variable references. The block takes two NSIntegers (x and y). You might notice that everything to the right of the equal sign looks a lot like a C function.

You can call a block by using the special unicorn character as shown Below:

Unicorn_code

Just Kidding…

Here’s how you would actually do it:


1
NSInteger sum = mathOperation(1,2);

Go ahead and create single view controller and add some code to the viewDidLoad method as follows:


1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    NSInteger (^mathOperation)(NSInteger x, NSInteger y) = ^NSInteger(NSInteger x, NSInteger y){

        return x + y;
    };

    NSInteger sum = mathOperation(1,2);
    NSLog(@"Sum of 1 and 2 is: %i", sum );
}

Run the application and you should see the correct result in the output window.

In this code, we first declare the block, then call it and then print the value to the screen. This is a very simple use of a block.

What Do We Use Blocks For?

Let’s pause for a second and give a little more info on why we use blocks. Blocks are handy because they are like a chunk of code you can execute at any time. Because blocks are actually objects in Objective-C, we can pass this chunk of code into a method just as any other object. In addition blocks are lexical. This means they can read and capture the current state of any local variables, parameters, and even variables on the stack.

To clear this last statement up, here’s a quick example:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    NSInteger z = 20

    NSInteger (^mathOperation)(NSInteger x, NSInteger y) = ^NSInteger(NSInteger x, NSInteger y){

        return x + y + z;
    };

    NSInteger sum = mathOperation(1,2);
    NSLog(@"Sum of 1 and 2 is: %i", sum );
}

Notice here that we have defined the NSInteger “z” outide the block brackets? This is totally acceptable. Furthermore, the current value for z will be captured the instant we call the block. the NSInteger z will be read-only unless we put a __block in front of it.

to make our z variable writable you would do the following:


1
__block NSInteger z = 20

Typically, blocks are used for one of the following:

  • Completion Handlers
  • Error Handlers
  • Notification Handlers
  • Enumeration
  • View animation and transitions
  • sorting

Blocks are also extremely handy when it comes to multi-threading. We’ll get into that on part 2 of this tutorial.

Using Them In Methods

Now let’s explore how you can use them in a method. First we’re gonna create a method that accepts a block. Go ahead and add a new method to your viewController.h and viewController.m files below viewDidLoad:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
viewController.h

@interface ViewController : UIViewController

-(void)performMathOperation:(void (^)(NSInteger,NSInteger))mathOperationBlock;

@end

viewContrller.m

-(void)performMathOperation:(void (^)(NSInteger,NSInteger))mathOperationBlock
{

   mathOperationBlock(1,2);

}

Here we setup a method that accepts a block with two NSIntegers as inputs and a void return type.

Now that our method is setup we can go ahead and call it. Go ahead and do that by modifying the viewDidLoad method:


1
2
3
4
5
6
7
8
9
10
- (void)viewDidLoad
{
    [super viewDidLoad];

    [self performMathOperation:^(NSInteger x, NSInteger y) {

        NSLog(@"This is the value for x: %i", x);
        NSLog(@"This is the value for y: %i", y);
    }];
}

Here we have deleted the previous code in the viewDidLoad method and replaced it with a block method call instead. Go ahead and run your application and you should see the following similar output in your output window:


2013-06-19 00:35:29.188 FunWithBlocks[42463:c07] This is the value for x: 1
2013-06-19 00:35:29.188 FunWithBlocks[42463:c07] This is the value for y: 3

You’ll see how we can execute the block from another method. In this case we are passing the values 1 and 3 into the block from the performMathOperation method. These values are available to us from where we call the block.

I’m sure at this point your still a bit fuzzy on how to use them and why they are helpful. So let’s create completion handler to clear things up a bit.

Creating a Completion Handler

Sometimes it’s nice to get some feedback from a method that indicates whether or not it executed successfully. Without blocks, You would have to implement some observer or delegate pattern to get this done. Blocks make for a much cleaner approach. To get a full sense of how blocks are helpful, let’s start by doing a completion handler the old way.

A Simple Completion Handler Without BLocks

Start off by creating a new NSObject class and title it OldSimpleCounter. This class will simply start counting to 10,000 and display “Ten Thousand Counts Finished” in the output window when it’s done. I know this is a stupid simple example, but I think it gets the point across.

Edit the OldSimpleCounter.h file as follows:


1
2
3
4
5
@interface OldSimpleCounter : NSObject

-(void)countToTenThousandAndNotifyObserver:(id)object withSelector:(SEL)selector;

@end

Now Add the following code to the oldSimpleCounter.m file as follows:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@implementation OldSimpleCounter

-(void)countToTenThousandAndNotifyObserver:(id)object withSelector:(SEL)selector;
{
    int x = 1;
    while (x < 10001) {

       NSLog(@"%i", x);
           x++;
   }



    [object performSelector:selector withObject:object];

}

@end

Now add two new methods to the end of ViewController.m file as follows:


1
2
3
4
5
6
7
8
9
10
11
12
-(void)startCountingToTenThousand
{
    OldSimpleCounter *oldSimpleCounter = [[OldSimpleCounter alloc] init];
    [oldSimpleCounter countToTenThousandAndNotifyObserver:self withSelector:@selector(tenThousandCounts:)];

}

-(void)tenThousandCounts:(id)sender
{

    NSLog(@"Ten Thousands Counts Finished");
}

Go ahead and call the startCountringToTenThousand method from the viewDidLoad method by adding the following line of code:


1
[self startCountingToTenThousand];

Of course you should be importing the OldSimpleCounter.h into your ViewController class as well:


1
#import "OldSimpleCounter.h"

Now run it and you will see the output window count to ten thousand and then you’ll see the text “Ten Thousand Counts Finished” when the count reaches 10000.

Not too difficult right? You can see here that we set the ViewController class as the observer and the tenThousandCounts as the selector. The countToTenThousandAndNotifyObserver method in the OldSimpleCounter class receives these values, does some work and then calls the observing class and the method provided as the selector. So we’re basically telling the OldSimpleCounter which method in which class(in this case self or ViewController) to call when it’s done doing some work.

Now let’s take a look at a block approach!

A Simple Completion Handler Using Block Approach

Go ahead and create a new class and title it “NewSimpleCounter”. Here’s how you would setup the .h and .m files for that new class:

NewSimpetCounter.h:


1
2
3
4
5
@interface NewSimpleCounter : NSObject

-(void)countToTenThousandAndReturnCompletionBLock:(void (^)(BOOL))completed;

@end

NewSimpleCounter.m

@implementation NewSimpleCounter


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-(void)countToTenThousandAndReturnCompletionBLock:(void (^)(BOOL))completed
{

    int x = 1;
    while (x < 10001) {

        NSLog(@"%i", x);
        x++;
    }

    completed(YES);


}

@end

So what we have done so far as created a new method that accepts a block and the block has a BOOL type input parameter. Then, we call the block once the while loop is done inside our method.

So, let’s call the block method from within our viewController class’ viewDidLoad method using these lines of code:


1
2
3
4
5
6
7
8
9
10
11
12
13
//[self startCountingToTenThousand];

NewSimpleCounter *newSimpleCounter = [[NewSimpleCounter alloc] init];
[newSimpleCounter countToTenThousandAndReturnCompletionBLock:^(BOOL completed){

   if(completed)
   {

       NSLog(@"Ten Thousands Counts Finished");
   }


}];

Go Ahead and run it! Make sure you import the NewSimpleCounter.h file into the ViewController.m file first. The output window should yield the same result as earlier.

Now isn’t that much cleaner? We have one method that is easy to read in our NewSimpleCounter class and we have reduced two methods in the ViewController class to one method. I know this doesn’t immediately look like a big deal, but when you get into situations with multiple callbacks and error handling, blocks can significantly cut down on code complexity. Blocks can also simplify the use of delegate patterns. If you haven’t already, go check out Recipe 22 for an awesome way to simplify the UIAlterView delegate pattern using blocks.

That’s it for this recipe. The next recipe I’ll be doing will continue on this block discussion and cover their use in multi-threading and asynchronous operation.

About Joe Hoffman

I am An Electrical Engineer that spends a lot of my off time doing web development and other programming. Currently I am trying to expand my knowledge with iOS and I find that writing tutorials helps me learn more thoroughly as well as provide some useful info to others.

Comments

  1. > A block isn’t exactly an object […] you wouldn’t be able to send a message to a block.

    Try it.

    Blocks are absolutely an Objective-C object (isa pointer and all) and will happily accept, but are not always able to respond to, any message it receives:

    NSLog(@”%@”, [^(){printf(“\n”);} class]); //

    NSLog(@”%@”, [[[^(){} superclass] superclass] superclass]); // NSObject

    While (IIRC) the private classes to which blocks belong don’t implement any methods of their own, they will respond to anything that an NSObject instance does. You can send a block -copy instead of passing it to Block_copy, for instance.

    • Joe Hoffman says:

      Hi Lowell,

      Thanks for the clarification! One of the wonderful things about the internet is it keeps me honest. I’ll update the article accordingly. Hopefully I haven’t caused irreparable damage to those who have already read it.

  2. Tran Dung says:

    Thank you so much

  3. Very nice tutorial style! I like that you are succinct without a lot decorative fluff. Is “Implementing Blocks Part 2” available yet?

  4. Joe Hoffman says:

    Hi Ed!

    Thanks for the feedback! Here is the link for part II
    http://nscookbook.com/2013/07/ios-programming-recipe-27-implementing-blocks-part-ii/

    for future reference you can find a listing of all recipes under the recipes tab at the top.

  5. 1. What about the part when we add z = 20? Whats so important about that lexical bit? I think i understand why but Im not sure. I thought you were going to do something with z to show how it changed in and after the block.

    2. Confused as to what exactly this is doing or what its for:

    -(void)performMathOperation:(void (^)(NSInteger,NSInteger))mathOperationBlock{
    mathOperationBlock(1,2);
    }

    3. Related to #2, I can almost feel it. This is the closest Ive ever been to understanding the use of blocks and completion handlers. Im trying to understand these 2 lines of explanation:

    “So what we have done so far as created a new method that accepts a block and the block has a BOOL type input parameter. Then, we call the block once the while loop is done inside our method.”

    The method count…accepts a block…Check!
    The block has a bool input…Check!
    We run the count method from view controller…Check!
    The minute this count… method is called, it goes to the count… method before performing the if(completed) code…i think?
    It runs the code inside the count…method…
    It reaches the end of the while loop…
    It sets the completed() block to YES…
    So now it comes back to viewDidLoad’s block and if tests positive…

    A little confused…

  6. Hi Joe, thanks for the article, it was really useful! Saved to my Evernote for future references. 🙂

    Also, there is a typo in “UIAlterView”.

    Thanks,

  7. Don McBrien says:

    hello Joe,
    mind if I ask about the two approaches? It seems to me that in OldSimpleCounter, tenThousandCounts: will be called when the count is done. Meanwhile the app could have gone ahead with other work (assuming we put the counter in another thread). In NewSimpleCounter, we immediately ask is the job completed and probably it isn’t.
    Now you didn’t use threads but if you’re interested in completion, that’s probably what you have in mind.
    So aren’t we doing two different things here?
    Thanks
    Don

    • Joe Hoffman says:

      Hi Don,

      I addressed a bit of this in the Blocks Part II where I used GCD to take a process onto another thread to prevent blocking of the main thread. Although, I probably should have added more info in the Blocks II recipe about completion handlers on multiple threads. My intention was to keep it simple and introduce concepts one step at a time so as not to confuse the beginner.

      Thanks for the feedback!
      Joe

  8. Thank you so much!
    This tutorial was described as easy to understand. It’s even better than Apple official library!I Love this!

    Again, Thank you for sharing your knowledge of this!

Speak Your Mind

*

css.php
Privacy Policy