This chapter is from the book

This chapter is from the book

One shortcoming of C and Objective-C is code that performs a particular task becomes scattered around the code base. Say you are performing an operation on a C array of People structs and you need to sort the list by last name. Luckily, there is the library function qsort() to sort the array. qsort() is well-optimized and does its job well, but it needs some help. It does not know how items are compared to each other so that they end up in the proper sorted order.

The compare function is not close to the invocation of qsort(). If you want to know exactly what the comparison is doing while you are reading or maintaining the code, you will need to find personNameCompare(), perhaps look at surrounding code, and then return to your original place.

Similarly, in Cocoa you frequently initiate some process that is handled in a place distant from the initial call, kicking asynchronous work that is completed in callbacks. Say the user pushes a button to load an image, and an NSOpenPanel is displayed:

The initiation of the open panel is separated both in time and space from the handling of the open panel's results. You need to find a place to hide any data that needs to be communicated from one place to another, such as in a context parameter, instance variable, or global variable.

Wouldn't it be nice to have these auxiliary chunks of code near where they are being invoked? That way you can take in the entirety of an operation in a single screenful of code without having to hop around your codebase.

Blocks are a new feature added by Apple to the C family of languages, available in Mac OS X 10.6 and later and iOS 4.0 and later. Blocks allow you to put code that does work on behalf of other code in one place.

The block is introduced by the caret with the code of the block surrounded by braces. Bill Bumgarner from Apple said that the caret was chosen because "it is the only unary operator that cannot be overloaded in C++, and the snowman is out because we can't use unicode."

The code inside of the block is not executed at the same time as the function or method call that contains the block. The NSLog above will not be executed when the NSBlockOperation has been created; instead, it will be called at a later time when the operation is finally run.

Blocks can take arguments. NSArray's -enumerateObjectsUsingBlock: will enumerate all objects in the array, invoking the block for each one. The block takes three parameters: the object to look at, the index of the object in the array, and a stop pointer to a BOOL. Setting *stop to YES will cause the iteration to cease before the array has been exhausted: