Example from Effective Objective-C 2.0 book (chapter 6, blocks).
typedef int(^MySuperBlock)(BOOL success, int result);
@interface MyClass : NSObject
@property (nonatomic, strong) NSString *name;
@end
@implementation MyClass
- (void)exploringTypedef {
MySuperBlock block = ^(BOOL success, int result){
//TODO: implement.
};
}
- (void)ivarCaptureExample {
//Blocks are objects.
void (^processBlock)() = ^{
//Is equivalent to self->_name = @"New name", so 'self' is captured by processBlock.
_name = @"New name";
NSLog(@"Please welcome %@", _name);
};
}
/*
Blocks are exist only inside the scope they allocated in (because blocks allocate
the region of memory on the stack).
*/
- (void)blockScopeIssueExample {
void (^block)();
if (/* some condition */) {
//This block is guaranteed to be valid only in this 'if' section.
block = ^{
NSLog(@"Hello world!");
}; //compiler can override memory where block is stored right after going out of this scope.
} else {
block = ^{
NSLog(@"Bye world!");
}; //same problem here.
}
block();
}
- (void)blockScopeIssueFixExample {
void (^block)();
if (/* some condition */) {
//By sending 'copy' to block, it is copied from stack to heap and become a ARC-object.
//It will support reference counter.
//Otherwise while it is on stack it is cleaned automatically at the end of the scope.
block = [^{
NSLog(@"Hello world!");
} copy];
} else {
block = [^{
NSLog(@"Bye world!");
} copy];
}
block();
}
/*
Global block.
It is allocated in global memory and will never be released.
This kind of blocks can't capture any state, such as variables.
*/
void (^block)() = ^{
NSLog(@"This is a block");
};
@end