A large portion of the code that we write for iOS apps is event driven.  An event occurs (such as an app being moved to the background, a view being loaded, a user tapping on the screen, etc.), and our code is called by the OS to see how we want to react.  There are several different conventions we follow to set ourselves up as event handlers: override inherited methods, implement delegate methods, pass @selector arguments as “callback” methods, etc.  Several years ago (with the release of iOS 4), an additional construct was added: the “block.”  Since that time, blocks have become increasingly predominant in iOS API methods, arguably even overtaking @selectors in terms of popularity.  Yet, I still run into developers who have managed to avoid using or writing methods that require blocks.  Their complaint is that the syntax is too confusing.  My hope with this article is to demystify the block syntax.

What is a Block?

The easiest way to think about a block is that it’s similar to a C-function, but has the ability to be passed as an argument into a method.  In addition, the block can include data that is in the enclosing method (known as a closure in other languages).  Since a block is similar to a function, let’s start by creating a function, and then modify it to satisfy the block syntax.

void helloBlockWorld() {
    NSLog(@"Hello Block World!");
}

This is a simple function that doesn’t accept any arguments, nor does it provide any return value to the caller.  It simply prints, “Hello Block World!” to the console.  As mentioned above, a key feature of a block is that it gives us the ability to pass executable code as an argument to a method.  What would it look like to pass this function as an argument to a method called testTheBlock:?

[self testTheBlock:
   void helloBlockWorld() {
     NSLog(@"Hello Block World!");
   }
];

The syntax here is pretty understandable (the function is passed as the argument to the testTheBlock: method).  Unfortunately, it is also invalid and would not compile.  With two small changes, we can fix this by turning the function into a block.

The first change is to remove the return type declaration (which, in the example above, is “void”).  To be clear, we can still return any value (or void) we choose, it’s just that we don’t declare it in the signature of the block (similar to a JavaScript function).

The second change is to replace the name of the function with the ‘^’ character.  Earlier I said a block is similar to a function… it’s more precise to say it’s similar to an anonymous function (which is why the ‘^’ character is used instead of a name).

Now our code looks like this (which is legal and will compile):

[self testTheBlock:
  ^() {
     NSLog(@"Hello Block World!");
  }
];

When you compare the block to the function above, the syntax should be much more understandable.  Part of the complexity, in terms of being able to read a block, can simply be due to the way whitespace is used.  The example above is typically written in a more compact style, which is arguably more difficult for a beginner to read:

[self testTheBlock:^(){NSLog(@"Hello Block World!");}];

 Parameters and Return Values

A block can accept any number of parameters and return any valid data type (just like a function).  Let’s create a slightly more complex “Hello Block World” function that lets the caller determine the greeting type, and returns the completed text:

NSString* helloBlockWorld2(NSString *greeting) {
    return [NSString stringWithFormat:@"%@ Block World!", greeting];
}

If we follow our rules for converting this function into a block (remove the return type and replace the function name with a ‘^’ character), we have:

^(NSString *greeting) {
    return [NSString stringWithFormat:@"%@ Block World!", greeting];
}

… and to complete the example, let’s pass the block into a method:

[self testTheBlock2:^(NSString *greeting) {
    return [NSString stringWithFormat:@"%@ Block World!", greeting];
}];

 Declaring a Method With a Block Parameter

Similar to the block itself, the syntax for defining a block parameter is a bit unusual when first encountered.  Let’s start by reminding ourselves of how a basic method signature is defined.  If I wanted to create a method that returns void and accepts an NSString parameter, I’d write something like this:

-(void)testMethod:(NSString *)theMsg {
    // ...
}

The parameter type (NSString *) is defined in parentheses after the colon. To accept a block instead of an NSString *, we’ll need to replace what’s inside the parentheses with a description of the block type we are expecting.

-(void)testMethod:(BLOCK_PARAMETER_TYPE_GOES_HERE)theBlock {
    // ...
}

Although we don’t include the return type declaration with the block itself, we do include it when declaring the block parameter type. Essentially, the block parameter type looks something close to a function signature…

Recall that the syntax of a function is:
<return type> <function name>( <param type> <param name>, … )
i.e., BOOL isAdmin(User aUser)

A block parameter type syntax looks similar:
<return type> (^) (<param type>, … )
i.e., BOOL(^)(User)

Simply add this block parameter type inside the parentheses used to declare a method parameter:

-(void)testMethod:(BOOL(^)(User))theBlock {
    // ...
}

If it’s an empty block like our original HelloBlockWorld example (no parameters are declared), use the keyword “void.”

Here are some more examples:

// If we want an empty block passed in to our method, such as
^(){
    NSLog(@"Hello Block World!");
}

// ...the parameter type is:
void(^)(void)

// If we want a block that accepts two NSString* and returns an NSString* - such as:
^(NSString *firstName, NSString *lastName) {
    return [NSString stringWithFormat:@"%@, %@", lastName, firstName];
}

// ... the parameter type is:
NSString*(^)(NSString*, NSString*)

// One last example... this accepts an NSInteger and returns a BOOL - such as:
^(NSInteger theNumber) {
    BOOL guessedRight = NO;
    if( theNumber == 3 ) {
        guessedRight = YES;
    }
    return guessedRight;
}

// ... the parameter type is:
BOOL(^)(NSInteger)

Let’s replace the NSString * parameter in testMethod: with the proper block type syntax and create a test for it:

// Expects a block that takes no arguments and returns void
-(void)testMethod:(void(^)(void))theMsg {
    theMsg();
}

-(void)runTest {
    [self testMethod:^(){
        NSLog(@"Hello Block World");
    }];
}

Note that the block is executed by using the local parameter name (theMsg) and adding parentheses.  If you’ve ever passed in a function pointer to a JavaScript function, this syntax should seem very familiar.

Let’s finish with the “guess the number” example – note that the block accepts a parameter, which is passed in by the caller: guessTheNumber(5):

-(void)testMethod:(BOOL(^)(NSInteger))guessTheNumber {
    BOOL winner = guessTheNumber(5);
    if( winner ) {
        NSLog(@"We won!");
    }
    else {
        NSLog(@"We lost.");
    }
}

-(void)runTest {
    [self testMethod:^(NSInteger theNumber) {
        BOOL guessedRight = NO;
        if( theNumber == 3 ) {
            guessedRight = YES;
        }
        return guessedRight;
    }];
}

 Local Variables

Blocks have access to any methods declared in the enclosing method, as long as they are defined before the block.  In this example, an NSString * is accessed inside the block:

-(void)runTest {
    NSString *testStr = @"Testing!";
    [self testBlockVariables:^() {
        NSLog(@"The test string is: %@", testStr);
    }];
}

-(void)testBlockVariables:(void(^)(void))tester {
    tester(); // runTest prints: "The test string is: Testing!
}

The one issue here is that the variable is treated as a const.  Therefore the value cannot be changed inside the block.  If you want to be able to modify the original variable, you need to declare it with a __block qualifier (note: there are two underscores before the word ‘block’).

-(void)runTest {
    __block NSString *testStr = @"Testing!";
    NSLog(@"%@", testStr); // Prints: Testing!
    [self testBlockVariables:^() {
        testStr = @"Changed!";
    }];
    NSLog(@"%@", testStr); // Prints: Changed!
}

Why Use Blocks?

My first response to this question is a practical answer: because most new methods in iOS APIs require them.  Beyond that…  my top 3 reasons for using blocks:

  1. A @selector requires a method to exist and be exposed as part of a class’s API.  This runs the potential risk of a method, which was created for one specific use case, to be used in a manner unintended (even a private method can be invoked in a manner unintended).  A block, when directly passed as an argument to a method, is less visible than a private method!  The block is only available to the method it is passed to (assuming the method doesn’t further expose or pass it on).
  2. The definition of a block, passed to a method, is typically located at the point it is used.  Therefore, the purpose of the method invocation is more visible & understandable (compared to a @selector that you may have to locate elsewhere).
  3. A block has a special relationship with its enclosing method, which gives it the ability to share parameters as they exist at a specific moment in time.  This allows a block to provide highly contextual functionality that may change for each instance it is used.