Online Book Reader

Home Category

Cocoa Programming for Mac OS X - Aaron Hillegass [112]

By Root 842 0
to be passed in through a single void pointer argument.

Perhaps you are starting to see that this approach has a number of downsides. Maintaining C functions for custom sorting forces our input parameters to be awkwardly funneled through a void pointer. An NSDictionary or custom C struct will get the job done, but they add complexity. Additionally, the C function must be separate from the code that calls it, making it more challenging to efficiently maintain the code.

There is, however, an elegant solution to this problem: blocks. You can think of blocks as functions that can be passed around just like an object. Consider the following solution. The caret (^) in the following code is the start of the block:

- (NSArray *)brainsForFlags:(NSInteger)flags

{

NSArray *allBrains = [[self game] allBrains];

return [brains sortedArrayUsingComparator:^(id a, id b) {

Brain *brainA = a;

Brain *brainB = b;

float criteriaA, criteriaB;

if (flags & FrenzyMode)

{

criteriaA = [brainA iq];

criteriaB = [brainB iq];

}

else

{

criteriaA = [self distanceToBrain:brainA];

criteriaB = [self distanceToBrain:brainB];

}

if (criteriaA == criteriaB) return NSOrderedSame;

else if (criteriaA < criteriaB) return NSOrderedAscending;

else return NSOrderedDescending;

}];

}

We’ll get into the particulars of blocks syntax in the next section. Until then, let’s look at some of the more interesting parts of this method. The sortedArrayUsingComparator: method takes a block as its only parameter. You’ll notice that blocks look quite a bit like C functions. They have arguments and a body. Where they differ from C functions is that they do not have to be named (they are anonymous) and can be treated just like an expression. In fact, they are objects.

This particular block takes two arguments (a and b) and refers to variables that are defined outside the block (self and flags). This is one of the more useful aspects of blocks: They capture the value of variables from the scope outside the block. There’s generally no need to package up your variables to squeeze into the argument list: You can simply use the variables that are in scope.

Blocks provide an elegant way to address such problems as nontrivial sort criteria, as well as much more sophisticated problems. Next, we’ll talk about the particulars of using blocks.

Block Syntax


Blocks enable the developer to create objects that encapsulate instructions, inline with the rest of their code, which capture the values of variables that are within scope. The resulting object can then be passed about and even copied, just like any other object.

The block syntax can be a little off-putting at first (it is not dissimilar from C function pointer syntax), but the benefits far outweigh the time you will spend getting used to it. Let’s define a simple block:

int captured = 1; // Local variable 'captured'

int (^offsetter)(int) = ^(int x) { return x + captured; };

On the first line, we create a local variable: captured. Next, we declare a variable named offsetter, which is a block. Whenever we are creating or defining a block, we use the ^ operator. This block returns an integer and takes an integer as its only argument.

On the right side of the equal sign, we define the block (note the ^, again). This part looks a lot like a C function definition. We specify that the integer parameter will be called x, and then we provide the body of the block in braces. An annotated version is shown in Figure 29.1.

Figure 29.1. Anatomy of a Block

Aside from the magic of creating a block of code on the stack like this, two interesting things are happening here: First, our block definition does not specify the return type of the block. The compiler is smart enough to figure it out from the return statement. Second, we refer to the variable captured inside the block. A blocks programmer would say that we are capturing the value of captured in the block. This is a very powerful feature of blocks.

How do we call a block? As it turns out, it looks quite a bit like a C function

Return Main Page Previous Page Next Page

®Online Book Reader