Graphics Programs Reference
In-Depth Information
multiplier = 100;
NSLog(@"%d", [executor computeWithValue:2 andValue:5]);
// Get a pointer to the main operation queue and add a block to it
[[NSOperationQueue mainQueue] addOperationWithBlock:^void(void){
NSLog(@"%d", [executor computeWithValue:2 andValue:5]);
}];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
NSLog(@"About to exit method...");
return YES;
}
Build and run the application. Notice the console reports it is exiting
applica-
tion:didFinishLaunchingWithOptions:
, and shortly thereafter, you see the
result of the
executor
running its equation. Using
addOperationWithBlock:
on
the main queue is pretty common. Many times, you will want the run loop to finish draw-
ing views and clearing the autorelease pool before a block is executed.
This makes sense except for one small thing: the variable,
executor
, is the only vari-
able that points to the
BNRExecutor
instance. When
applica-
tion:didFinishLaunchingWithOptions:
finishes, the block has yet to run, but
the
executor
variable is destroyed - which should cause the
BNRExecutor
to also be
destroyed. However, the
BNRExecutor
is clearly not destroyed because the block,
which sends a message to the executor, runs without a hitch. (If
BNRExecutor
was
already destroyed when the block executed, you'd get a crash.)
What, then, keeps the
BNRExecutor
alive? A block keeps a strong reference to any ob-
ject it references within its scope. Thus, any time you send a message to an object or use
that object in any way within the block, it will be kept around as long as the block exists.
In the case of
addOperationWithBlock:
, the block is kept until it is executed, and
then it is discarded. We can test this out. In
BNRExecutor.m
, implement
dealloc
to
print out when the executor is destroyed.
- (void)dealloc
{
NSLog(@"Executor is being destroyed.");
}
Build and run the application. Notice that the
BNRExecutor
is destroyed after the block
is executed. The block held the last strong reference to it and when the block was des-
troyed, it lost the last reference to the object. This works because the block captures the
variable that points to the
BNRExecutor
in the same way it captures any other variable.
The compiler is very smart: it figures out that this is a pointer to an object and gives the
block ownership of that object.