在数组中存储块

noi*_*oys 50 memory-management objective-c objective-c-blocks

在Objective-C中,我知道块被认为是对象,所以我想知道是否可以将它们存储在数组中.这引出了一个问题,是阻塞第一类对象还是只是为了在对象之间传递它们而被视为对象?如果它们是第一类对象,那么它们不应该存储在数组中吗?

bbu*_*bum 90

编辑:在ARC下,没有太多细节,您现在可以像其他任何对象一样向集合添加块(参见讨论).

我在下面保留原始答案,因为它包含一些有趣的技术细节.


这引出了一个问题,是阻塞第一类对象还是只是为了在对象之间传递它们而被视为对象?如果它们是第一类对象,那么它们不应该存储在数组中吗?

块是Objective-C对象,其行为与其他NSObject类似,但有几个主要区别:

  • 块始终由编译器生成.当执行通过块声明时,它们在运行时实际上是"alloc/init".

  • 最初在堆栈上创建块.如果块要比当前范围更长,则必须使用 Block_copy()或copy方法将块移动到堆(请参阅下面的ARC点).

  • 除了内存管理之外,块实际上没有可调用的API.

  • 要将块放入集合中,必须先将其复制. 总是.包括在ARC下. (请参阅注释.) 如果不这样做,则存在堆栈已分配阻止的风险,autoreleased您的应用程序将在以后崩溃.

  • 复制基于堆栈的块也将复制所有捕获的状态.如果要制作块的多个副本,则复制它一次更有效,然后复制副本(因为复制副本只会碰到保留计数,因为块是不可变的).

  • 在ARC下,从方法或函数返回一个块"正常工作"; 它将被自动复制到堆中,并且返回将实际上是一个自动释放的块(编译器可能在某些情况下优化自动释放).即使使用ARC,您仍需要在将块粘贴到集合中之前复制块.

我写了几篇博文,都提供了介绍和一些提示和技巧.你可能会发现它们很有趣.

而且,是的,将'em添加到词典中非常有用.我已经编写了几个代码,我把块作为命令处理程序放到字典中,其中键是命令名.非常便利.

  • 在ARC下,添加到集合时不再需要复制块!Apple在其"*ARC过渡指南*"中表示,但该指南相当过时了.请查看http://blog.parse.com/2013/02/05/objective-c-blocks-quiz/ - 尤其是示例B和示例C的答案,以及最后的"*结论*" .甚至在ARC下复制块的需要来自于clang中的编译器错误(很久以前就已经修复)并且只是一个解决方法,因为Apple在发布下一个Xcode版本之前不能等待这个bug被修复. (17认同)
  • 我刚刚测试了Mecki在Xcode 5(Apple LLVM 5.0)提供的最新`llvm`版本上所说的内容.该错误不再存在,因此可以安全地将块存储在容器中而不需要ARC下的显式副本. (3认同)
  • 谢谢@Mecki。我需要回去编辑我所有关于积木的答案。:) (2认同)

Edu*_*coz 40

是的,块确实是对象,您可以将它们放在数组中:

NSMutableArray *arr = [NSMutableArray new];
[arr addObject:^(){NSLog(@"my block");}];
void (^ myblock)() = [arr objectAtIndex:0];
myblock();
Run Code Online (Sandbox Code Playgroud)

这将把"我的块"放在控制台中.

  • 在添加到集合之前,必须复制块*.总是.即使在ARC下. (18认同)
  • @newacct只是为了记录(一切都已存档)以及将来遇到这种情况的所有人:John McCall说你不需要ARC中的Block_copy.见http://bit.ly/1br5J7Z如果您不知道John McCall是谁,请参阅http://bit.ly/19gnnGD并搜索他的名字.我相信John McCall比SO用户告诉你的大约一百万倍.在启用ARC的情况下,编译器应该始终知道何时必须将块复制到堆(如果需要的话,任何失败都是错误),不需要调用`Block_copy`; 它甚至可能会破坏编译器优化. (9认同)
  • @Mecki:这是完全错误的.在C中,仅仅因为某些东西没有崩溃并不意味着它是正确的 - 它可能是未定义的行为.ARC规范中的任何内容都不保证在这种情况下将复制块.仅仅因为这个ARC编译器的这个版本碰巧插入副本并不意味着你可以依赖它. (5认同)
  • @bbum:不再需要在ARC下复制块,即使在添加到集合时也是如此.Apple在他们的过渡指南中这么说,但这只是解决了很久以前修复过的clang编译器错误.请参阅http://blog.parse.com/2013/02/05/objective-c-blocks-quiz/ - 特别是答案*示例B*,*示例C*和*结论*结尾(也链接)到一个LLVM维护者的帖子解释情况). (4认同)