Introduction to Blocks in Objective-C – Part 2


<!–

–>

In the first post on blocks, Introduction to Blocks in Objective-C – Part 1, I covered the basics for creating block variables, working with __block modifier and using typedef to define blocks. In this post I will show how you can pass a block as a parameter, use enumeration with blocks, as well as take a quick look at blocks and recursion.

Passing Blocks as Parameters

Within a number of iOS frameworks, methods are provided that accept a block as a parameter. As it relates to working with blocks, this is one area where things start to get interesting and you get a perspective on a few unique features offered through blocks.

For example, in the code below, I create an array of string objects, nothing new there. However, in iOS 4+NSArray now includes a method to create a set (NSSet) object from the array by passing in a block into the indexesOfObjectsPassingTest method. The block that I’ve written checks the length of each object in the array (each is object is string in this example), and return YES, only for those objects where the string is greater than 5 in length.

Now that we have a set that tells us which objects are of a specified length (or greater), let’s call a method in the NSSet object that will enumerate the values in the set and print the values of the relevant array entries – the method enumerateIndexesUsingBlock in NSSet will also accept a block as a parameter:

The output from the above is:

Array entry 1 contains: 12345678
Array entry 3 contains: 123abc

Using Stop to End Processing

Let’s take a closer look at the definition of indexOfObjectPassingTest method in the NSSArray object:

In the first example shown above, the only parameter in the block referenced was obj, where the length was compared to see if it was 5. When you need to stop processing a block based on some condition check, you can use the stop parameter.

Let’s say we have an array of dictionary objects that contain an account number and a boolean flag that indicates if the account is active:

NSArray *arrayOfDictionaryObjects = [NSArray arrayWithObjects:
    [NSDictionary dictionaryWithObjectsAndKeys:@"1234", @"accountID", [NSNumber numberWithBool:NO],  @"isActive", nil],
    [NSDictionary dictionaryWithObjectsAndKeys:@"2345", @"accountID", [NSNumber numberWithBool:NO],  @"isActive", nil],
    [NSDictionary dictionaryWithObjectsAndKeys:@"3456", @"accountID", [NSNumber numberWithBool:YES], @"isActive", nil],
    [NSDictionary dictionaryWithObjectsAndKeys:@"4567", @"accountID", [NSNumber numberWithBool:NO],  @"isActive", nil], nil];

If we had a need to process the array and find the first account which was flagged as active, we could once again use the indexOfObjectPassingTest method of the NSArray object, passing in a block, and looking at the value of the isActive key to find the first active account:

Notice how once the condition is met, we set the stop value to YES, this will stop any further processing of the block (after the ‘return YES’ statement or course).

Blocks and Enumeration

Enumeration is a common operation on objects, and there are numerous variations of block operations to help. In the code below I create a dictionary of timezone abbreviations and their names:

The output from the above looks like this:

Abbreviations: {
ADT = “America/Halifax”;
AKDT = “America/Juneau”;
AKST = “America/Juneau”;
ART = “America/Argentina/Buenos_Aires”;
AST = “America/Halifax”;

}

We can now enumerate over the dictionary keys and objects, using a block, to print out the abbreviations that have the prefix “America”:

The American timezones are shown as:

America Timezone: EDT
America Timezone: AST
America Timezone: PET
America Timezone: CLST
America Timezone: PST

Let’s look at one more example using the same dictionary that was defined above, where one value in the dictionary is the account number and one indicates if the account is active:

NSArray *arrayOfDictionaryObjects = [NSArray arrayWithObjects:
    [NSDictionary dictionaryWithObjectsAndKeys:@"1234", @"accountID", [NSNumber numberWithBool:YES],  @"isActive", nil],
    [NSDictionary dictionaryWithObjectsAndKeys:@"2345", @"accountID", [NSNumber numberWithBool:NO],  @"isActive", nil],
    [NSDictionary dictionaryWithObjectsAndKeys:@"3456", @"accountID", [NSNumber numberWithBool:YES], @"isActive", nil],
    [NSDictionary dictionaryWithObjectsAndKeys:@"4567", @"accountID", [NSNumber numberWithBool:NO],  @"isActive", nil], nil];

To print the active accounts from the array of dictionaries, (notice for this example both the 1st and 3rd entries are set as active), we can enumerate the array using a block and check the value of the “isActive” key in the dictionary:

The output is shown as:

Active account: 1234
Active account: 3456

Recursion and Blocks

Writing a recursive block is pretty straight-forward. Let’s look at a few examples.

Calculating factorials is a common example when speaking recursion. 4 factorial is expressed as 4!, which evaluates to the sum of 4 * 3 * 2 * 1. A block variable below is defined to calculate factorials:

There is really nothing special about recursion and blocks, with the one important exception, the __block modifier is required in the definition of the block.

A discussion on recursion wouldn’t be complete without visiting the Fibonacci sequence. If it’s been a while, the Fibonacci sequence goes as follows:

0 1 1 2 3 5 8 13 21 34 21…

where the next number in the series is the sum of the previous two values: 0 + 1 = 1; 1 + 1 = 2; 1 + 2 = 3 etc.

The sequence is written as:

A partial series follows:

Below is block that will generate a value in the Fibonacci sequence:

To get the value for F7:

int x = 7;
NSLog(@”Fibonacci: %d”, fibonacci(x));

The output is: Fibonacci: 13

What’s Next…

Honestly, I’m not quite sure where this will go next – callbacks and view animations/transitions might be a good direction…

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s