New to Objective-C is the block syntax. A block is a section of code that is grouped together and designed to be treated like one statement. Blocks also package up the lexical scope of variables and functions within its environment. Blocks are found in many languages including, but not limited to, Ruby, Javascript and Lisp. Blocks are objects and should be treated like such!
Programming Language | Code Example | Colloquial |
---|---|---|
Ruby |
[1, 2, 3, 4].each do |i| puts i end |
Block |
Lisp |
((lambda (a b) (+ b a)) 1 2) |
Lambda function |
Javascript |
var foo = function () { var j = 42; } |
Anonymous Function, Closure |
Objective-C |
^BOOL(num1,num2){ return [num1 isEqualToNumber:num2]; } |
Block |
Now there are other block structured languages out there but the few listed here are used to provide a basis for understanding if you’re coming from another language where you may have experienced this concept.
Objective-C inherited blocks from the C language, which it is a superset of. Apple has created an extension of the C language implementing blocks. Syntactically, blocks start with the carrot symbol, followed by its return type followed by arguments (enclosed by parenthesis) and finishing off with the code body defined between curly braces.
^Return Type (Arguments) {Code Body}
The blocks return type and arguments are both optional parameters, leaving them off will not effect the block.
^{Code Body}
You can pass blocks to a function:
Repeat(12, ^{ [str appendFormat:@"rand: %d", rand()]; });
Scoped variables (by default) are immutable in blocks. To make these mutable you prefix the keyword __block.
For example
__block int count = 0; //mutable thanks to the __block keyword int specialValue = 50; //immutable inside the block ^{ // do some calculation int newValue = someCalculatedValue + specialValue; count++; //increment the count every time we do this calculation }
A good example of when you might want to use a block may be a callback. Since callbacks are generally a grouping of code that will run after an operation.
One Comment
Thanks. The various docs on blocks do not illustrate the difference in syntax when defining a type that holds a block as opposed to the block definition itself. Turns out the syntax is different. XCode was saying “Expression Expected” if I used the same syntax for defining the block as I was using to typedef a variable to hold it. Subtle but important difference….For typedef’s, the Return Type precedes the caret (^) while it must follow the caret when defining the block itself.
//*correct* syntax for defining a data type to hold a block
typedef NSArray* (^my_block_type_t) (NSData *data);
//*wrong* syntax for defining the block
my_block_type_t blockVariable = NSArray* (^my_block_type_t) (NSData *data)
{code body};
//*correct* syntax for defining the block
my_block_type_t blockVariable = ^NSArray *(NSData *data)
{code body};
As you explained:
^Return Type (Arguments) {Code Body} is the correct syntax for defining a block, while
typedef Return Type (^my_block_type_t) (Arguments) is the correct syntax for defining a new type that stores a block.
Thanks again.
Thanks again.