iOS SDK: Blocks and Enumeration

In iOS 4, Apple brought Blocks to iOS. Put simply, a block is a variable type that stores executable code. This quick tip will provide a brief, general overview of blocks and teach you how to use them for enumerating over objects.


Blocks Overview

As a programmer, you're used to data types like String, which is a variable type for text. We also are aware of things like int, float, and double, which are variable types to store numeric values. Finally, we know about things like NSObject, which is a foundation level class that allows us to bundle various collections of both data types and methods (a.k.a. functions). Blocks bring something significantly different to the table, providing a data type for executable code storage.

If that doesn't make sense to you, don't worry: blocks can be tough. Their purpose and function becomes much more clear upon seeing examples of their use. One of the most popular types of patterns in which blocks are used is for providing "completion blocks" to objects who perform some kind of asynchronous operation. The following is an example of a method signature provided in my UIView that takes advantage of accepting a completion block from a user:

That final completion parameter there is a block. As with all Objective-C methods, the method has named parameters. The animations and completion parameter are the blocks. You can tell because of the ^ character. This character is used to define a block. While a block variable type holds executable code, the block type itself must be defined. Just like when writing code within a method, blocks can provide objects to the code which it holds. Here we see the animation block defined first:

We can see this block returns void and provides void. In this block you would change all the UIKit animatable properties you would want. The completion block is a bit different though.

In this block we can still see that we will be returning void. However, this time our block will be returning the completion BOOL for us to utilize if we like. When actually implementing this method in Xcode, the IDE does a lot of the work to get you past the somewhat jarring syntax of blocks. Once tabbed over to the parameter input for a block when calling a method, in Xcode 4 and above, hit enter and Xcode will create the outline of the block for you.

Animation Execution With Blocks

Perviously, you might imagine providing this functionality through the delegate pattern, but blocks are here now to allow for greater flexibility and will only become more popular with future versions of the SDK.


Sample Code

Grab the sample code for this project on GitHub. Play around with the code on your own as you follow along with this tutorial.


Enumeration

So, blocks are awesome. You will see them a lot as an iOS developer. One very common operation that can be performed with Blocks is enumeration. There are three major Foundation objects you would want to enumerate with.

  • NSArray/NSMutableArray: An ordered collection of objects
  • NSDictionary/NSMutableDictionary: An unordered collection of key-value objects.
  • NSSet/NSMutableSet: An unordered collection of unique objects

NSDictionaries

Each of these objects has different logical rules enforced on them to achieve different functions. As a result, enumerating through each is slightly different. We will look at how iOS 4 and greater provides block enumeration options for you to take advantage of. Let's first start by defining a sample dictionary to use.

Great. So when we enumerate a dictionary we are going to need to be provided each key and value and hopefully have the possibility to break out of the enumeration if we choose. Since dictionaries are unordered we won't be provided with an index. This is exactly what we find when looking at the new block based enumeration method for dictionaries.

In this case, the block we provide will be injected with a key, obj, and stop BOOL pointer. This should give us all the tools we need to enumerate through this dictionary. Let's enumerate over all the keys and values and print them out.

And here's the output:


NSArrays

Great! Dictionary enumeration was easy. Let's checkout out array enumeration now. Let's grab the array returned by the allKeys method on our sample dictionary and work with that first.

An array is an ordered collection of objects. So when enumerating through an array, it would make sense to be provided the an object, its index, and a way to break out of the enumeration. Let's look at the NSArray instance method signature for enumeration.

Looks like exactly what we need. Our block is provided an object, its index, and a stop BOOL pointer to escape enumeration. This specific enumeration method also allows us to pass in an NSEnumerationOption. To demonstrate this, I am going to pass in the option to do the enumeration in reverse. With this in place we should see print outs from highest index to lowest. Let's enumerate over this array and print out all its objects along with their instances.

And here's the output:


NSSets

Ok, two down with one to go. NSSets are like arrays except they are unordered and hold a UNIQUE set of objects. This means that you can not have more than one of any given object in the collection. Our original dictionary had two different "I am fine." values. So, let's create a set from the allValues array provider on our dictionary.

Now that we have a set to work with, we should enumerate it. Since a set is an unordered collection of unique objects it would make sense that our enumeration block would be only supplied with an object and a way for us to escape enumeration.

Looks perfect. Let's enumerate over the set and print out the values. Remember, we should only have 5 values printed here because the set holds only unique values and we had a repeat value in our dictionary.

And here's the output:

Escaping Enumeration

So these all look pretty straightforward to use. But what about this BOOL *stop pointer we keep seeing. This is the flag you can set to stop your enumeration. Block based enumeration checks this flag on every loop before continuing. For a final example let's loop through our array again. This time, let's not do it backwards and stop once we get to index 1. We would accomplish that with:

It should be noted that when you set the flag to true, the block will execute all the way to the bottom. The enumeration is only escaped just before the next begins. You can see that in the output below because even though we set our stop flag before the NSLog, we still see the log for index 1. Here's the output:

Tags:

Comments

Related Articles