I have some code that essentially boils down to this:
-(void)doSomethingWithBlock:(BlockTypedef)block
{
[Foo doSomethingElseWithBlock:^() {
block
The inner Block_copy()
isn't really relevant here. What you want to keep track of is whether a given block lives on the stack or on the heap. Consider this code based on your example:
@interface Foo : NSObject
@end
@implementation Foo
typedef void(^BlockTypedef)(void);
+(void)doSomethingElseWithBlock:(BlockTypedef)block
{
NSLog(@"block=%@", block);
BlockTypedef myBlock = Block_copy(block);
NSLog(@"myBlock=%@", myBlock);
myBlock();
Block_release(myBlock);
}
+(void)doSomethingWithBlock:(BlockTypedef)block
{
[Foo doSomethingElseWithBlock:^() {
block();
}];
}
@end
int main (int argc, const char * argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int i = 3;
BlockTypedef block = ^{ printf("i=%d\n", i); };
NSLog(@"block=%@", block);
[Foo doSomethingWithBlock:block];
block();
NSLog(@"block=%@", block);
[pool drain];
return 0;
}
This should be ok, but block
and myblock
are different kinds of blocks. block
is a stack block and has the scope of the calling stack. It will exist until main()
exits. myblock
is a malloc (heap) block, and will exist until it is released. You need to make sure that you don't try to take a non-copied reference to block
and use it after the stack is done. You can't stick block
in an ivar without copying it.
Joachim Bengtsson has the best write-up of this that I know of. @bbum has also written about it. (If bbum wanders in here and says I'm an idiot about this, then listen to him, but I think I'm right here.)