Objective c 没有复制的iOS块对象?
最近我了解到,如果需要保留块对象,我应该复制块,因为它是在堆栈上创建的 然后我回顾了我的一些代码。我发现我在做这样的事情:Objective c 没有复制的iOS块对象?,objective-c,ios,block,Objective C,Ios,Block,最近我了解到,如果需要保留块对象,我应该复制块,因为它是在堆栈上创建的 然后我回顾了我的一些代码。我发现我在做这样的事情: @implementation MyView ... -(void) addButton:(NSString *)title clickAction:(void ^(void)) action { [self.buttons addObject:@[ title, action ] ]; } -(void) createButtons { ... } ... @en
@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)
*非弧
*XCode 4.5在幕后,块实现由两部分组成:
- 块的可执行代码,以及
- 包含块中使用的变量值的数据结构
由于块实现不引用周围范围中的任何变量,因此其块的数据部分为空。这就是你的代码工作的原因:根本没有东西可以复制!但是,您还是应该添加块副本,因为否则,对块的代码进行一个小的更改就会中断应用程序,而编译器不会注意到任何东西。编译器会根据块的作用创建不同类型的块。如果一个块没有捕获任何变量,那么它可以由一个
NSGlobalBlock
表示(NSGlobalBlock
只不过是一个函数指针)。我怀疑这就是正在发生的事情。我很确定代码仍然可以工作,无论块有多复杂,因为action
被放置在NSArray
中,这将导致它被集合保留…@JodyHagins保留不是问题,堆栈上分配的主体超出范围将导致问题。当该方法存在时,在其内部创建的块将在内存的无效区域中结束。这就是为什么您需要将它复制到堆中。对-但是当NSArray保留它时,它会被复制到堆中。从那时起,NSArray中的对象将是堆版本,而不是原始堆栈块。如果对基于堆栈的块调用retain,它会将其复制到堆中,然后保留它。@JodyHagins我有理由相信,仅仅将retain
发送到堆栈对象不足以生成堆栈副本。块会得到特殊处理。我已经很久没有使用非弧形块了,我想它会Block\u copy
作为retain的一部分,因为它知道它在堆栈上(并且块在其他情况下会得到特殊处理)。。。但这将打破“保留必须返回相同实例”的定义。。。我甚至在发布最后一条评论之前做了一个小测试来证明自己。。。并且没有取消选中ARC框。。。我将删除我的帖子,并留下这条评论,以确认我是一个白痴。。。并承诺永远不会回答另一个非ARC特定的问题:-)谢谢,看来你和@dasblinkenlight有着相同的观点。我将接受dasblinkenlight的答案,因为他的答案更详细。