最近我了解到如果我需要保留一个块对象,我应该复制该块,因为它是在堆栈上创建的。
然后我回顾一下我的一些代码。我发现我做了类似的事情:
@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"); }];
}
基本上,我向MyView添加了一些按钮信息。在某些时候,MyView将创建按钮。单击该按钮时,MyView将找到相应的clickAction,并调用它。
奇怪的是,这个程序运行正常,没有例外,没有错误。
那么,为什么程序运行而不复制块对象?
其他信息: * iPhone应用程序(4.3 - 6.0) *非ARC * XCode 4.5
答案 0 :(得分:7)
在幕后,块实现由两部分组成:
只有块的第二部分放在堆栈上并复制到堆内存中;第一部分编译到程序的代码段,不会被复制。
由于您的块实现不引用周围范围内的任何变量,因此其块的数据部分为空。这就是你的代码有效的原因:没有什么可以复制的!但是,您应该添加块复制,因为否则对块的代码进行一些小的更改将会破坏您的应用程序而不会让编译器注意到任何内容。
答案 1 :(得分:0)
编译器根据块的作用创建不同类型的块。如果一个块没有捕获任何变量,那么它可以用NSGlobalBlock
表示(NSGlobalBlock
只是一个函数指针)。我怀疑这是发生了什么。