Online Book Reader

Home Category

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

By Root 846 0
call:

int answer = offsetter(2);

Note that answer is now 3 (2 + 1 = 3). What if we change the value of captured and call the block again?

captured = 64;

answer = offsetter(2);

The result is the same; answer is still 3 because the value of captured was captured when we defined the block. We cannot change captured from outside the block, and as it happens, we can’t change it from inside the block either. To do that, we need the __block type specifier.

By default, captured values are considered const within the block. If you need to modify a captured value from inside a block, you can add the __block type specifier:

__block BOOL modifiable = YES;

However, when a variable is marked with __block, the compiler treats it as what is essentially a global variable. Any block that was created with it in scope can change its value. Because it does come with some performance overhead, __block is not the default. Typically, it is more useful to capture only the value of a variable.

Memory and Objects within Blocks


When a block is defined, it is created on the stack. When the method or function it was defined in exits, the block is removed from memory along with all the other local stack variables. Sometimes, this is fine; we may wish to use the block only for the lifetime of that particular method call, as in our earlier brain-sorting example. The block is not used after the method returns.

Other times, however, we want the block to live on well after the method returns. Because the block is created on the stack, we must copy it in order to make sure that it is not deallocated with the current stack frame. For this reason, we recommend that you copy blocks when assigning them to instance variables:

@property (nonatomic, copy) int (^arithmeticOperationBlock)(int);

Just like we can capture scalar values within blocks, we can also capture pointers to objects. When a pointer to an Objective-C object is captured by a block, it is retained (a strong reference is formed). Any objects retained by the block are released when the block goes out of scope or is deallocated:

NSMutableArray *array;

array = [NSMutableArray array]; // retain count of 1, autoreleased

void (^simpleBlock)() = ^{

[array addObject:@"Q"]; // array pointer captured, retained

};

simpleBlock();

return; // simpleBlock is popped from stack, releases array

Note that variables with the __block specifier will not be retained by the block. This can be useful in preventing strong reference cycles. Note that this is still the case under ARC; however, ARC still considers a __block pointer a strong reference and thus retains it, unless you mark the variable __weak.

Consider the following code:

controller = [[MyController alloc] init];

controller.block = ^{

[controller doSomething];

};

This code creates a strong reference cycle. Do you see it?

MyController holds a strong reference to block. The block, however, holds a strong reference to the instance of MyController! The simplest approach is to use a temporary weak reference variable, since child objects (the block) should have only weak references to their parents (the controller).

controller = [[MyController alloc] init];

__weak MyController *weakController = controller;

controller.block = ^{

[weakController doSomething];

};

This resolves the strong reference cycle.

Availability of Blocks


Blocks are available beginning with Mac OS X 10.6 and iOS 4.0 and are an extension to the C language. Thus, you don’t need to be using Objective-C to take advantage of blocks, but you do need a compiler that understands blocks, as well as runtime support. If you are targeting Mac OS X 10.5 or iOS 2.2, PLBlocks from Plausible Labs provides a solution well worth looking into.

The first high-profile API to make use of blocks was Grand Central Dispatch, a Mac OS X concurrency library. As such, many people think of blocks as being useful only in multithreaded programming. We believe that blocks are extremely handy in a very broad range of programming

Return Main Page Previous Page Next Page

®Online Book Reader