Recently I learn that if I need to keep a block object, I should copy the block, because it's created on the stack.
Then I review some of my code. I found that I was doing something like:
@implementation MyView
...
-(void) addButton:(NSString *)title clickAction:(void ^(void)) action {
[self.buttons addObject:@[ title, action ] ];
}
-(void) createButtons { ... }
...
@end
...
// Somewhere in my project:
-(void) init {
MyView *view = [MyView new];
[view addButton:@"OK" clickAction:^{ NSLog(@"OK"); }];
[view addButton:@"Cancel" clickAction:^{ NSLog(@"Cancel"); }];
}
Basically, I add some buttons info to MyView. At some point, MyView will create the buttons. When the button is click, MyView will find out the corresponding clickAction, and invoke it.
The weird part is that this program works fine, no exception, no error.
So, why the program runs without copying the block object?
Other info : * iphone app ( 4.3 - 6.0 ) * non-ARC * XCode 4.5
Behind the scene, block implementation consists of two parts:
Only the second part of the block is placed on the stack and copied to the heap memory; the first part is compiled to the code segment of your program, and does not get copied.
Since your block implementations do not reference any variable from the surrounding scope, the data portion of their blocks is empty. That is why your code works: there is simply nothing to copy! However, you should add block copy anyway, because otherwise a small change to the code of your block will break your application without the compiler noticing anything.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With