This is a reference/cheat sheet of Objective-C blocks, introduced in iOS 4.0 and OS X Snow Leopard.
I keep forgetting the syntax, especially for writing methods that takes blocks. I hope you'll find this quickref useful, I certainly will.
Passing blocks
// The very simplest case.
[foo someMethod:^{
// Any code here.
}];
// A block that takes arguments.
[foo someMethod:^(NSString *something, BOOL somethingElse) {
// something an somethingElse can be used just like function arguments.
}];
Taking blocks
// Take a block with no arguments
- (void)someMethod:(void(^)())block;
// Take a block with arguments
- (void)someMethod:(void(^)(NSString *test, id anyObject))block;
// Any return type is OK.
- (void)someMethod:(BOOL(^)())block;
- (void)someMethod:(NSRange *(^)())block;
// Call a block
- (void)someMethod:(void(^)(NSString *test))block {
block(@"Yep");
}
The syntax can be described as:
a(^)(b);
a = Return type
b = Arguments
DRY block signatures
You can create a type for your block signature, if you're using the same signature many places.
typedef BOOL (^MyCustomBlock)(NSString *something);
- (void)myMethod:(MyCustomBlock)block {
BOOL result = block(@"whatever");
}
[foo myMethod:^(NSString *string){
return [string isEqualToString:@"give you up"]
}];
Inferring return type
The compiler will infer the return type of a block for unspecified return types, making return type specification optional. In the examples above, we have never specified the return type. This is how block creation looks with an explicit return type.
[foo someMethod:BOOL^{ return YES; }];
// Inferred return type, for good measure.
[foo someMethod:^{ return YES; }];
Using blocks returned from methods
This actually have a use case; storing blocks in a NSArray
or similar.
// Assuming "callbacks" is an NSMutableArray instance variable.
- (void)registerCallback:(BOOL(^)())callback {
[_listeners addObject:[[callback copy] autorelease]];
}
- (void)runCallbacks {
int i = [_listeners count];
while (i--) {
BOOL (^block)() = [_listeners objectAtIndex:i];
BOOL state = block();
// And so on...
}
}
As we can see, the return type isn't inferrable in this case.
The reason for copying the block in registerCallback:
is that the block can be (and most likely is) on the stack when we get it. Copying it moves it to the heap.
Recommended reads
- Joachim Bengtsson's awesome reference, you should read it from cover to cover.
- Cocoa with Love on how blocks are implemented.
- Blocks design patterns, article by Pragmatic Programmers.