651.288.7000 info@intertech.com

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.

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:?

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):

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:

 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:

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:

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

 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:

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.

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:

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

Here are some more examples:

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

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):

 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:

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’).

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.

Like What You've Read?

Subscribe to the Blog.

Every Friday we send that week's content from our Developers via email. Try it out!

Some ad blockers can block the form below.

You have Successfully Subscribed!

Pin It on Pinterest

Share This