我最近遇到一个苹果文件显示为块的以下财产申报:
@interface XYZObject : NSObject
@property (copy) void (^blockProperty)(void);
@end
此外,这篇文章指出:
注意:您应指定副本property属性,因为一个块需要被复制跟踪它捕获状态的原有范围之外。 这不是你需要担心使用自动引用计数时,它会自动发生有关的东西,但它的最佳实践的财产属性,显示结果的行为。 欲了解更多信息,请参阅模块编程主题。
我也读了建议块编程主题 ,但没有发现任何有关在那里。
我仍然好奇,为什么定义块属性为“复制”是最好的做法。 如果你有一个很好的答案,请尝试,如果有任何ARC和MRC的差异来区分。
谢谢
默认情况下,块在栈上创建。 这意味着他们只能在他们在创建范围存在。
如果你想通过发送后访问他们,他们必须被复制到堆copy
消息块对象。 ARC会为你只要检测到块需要它在创建范围外要访问做到这一点。作为最佳实践声明的任何财产块作为副本,因为这是它应该是在自动内存管理方式。
阅读在Objective-C栈和堆对象由Mike灰对堆与堆的详细信息。
块,默认情况下,在堆栈上分配。 这是一个优化的,因为堆栈分配比堆分配便宜得多。 堆栈分配是指,通过再次默认情况下,一个块将停止当它宣布退出的范围存在。 因此,与块属性retain
语义将导致悬摆指针到不存在了块。
移离堆叠的块的堆(并因此给它正常Objective-C的存储器管理的语义和延长的寿命),则必须复制通过块[theBlock copy]
, Block_copy(theBlock)
等。一旦在堆上中,块的寿命可以根据需要通过保持/释放它进行管理。 (是的,这适用于ARC过,你根本不用调用-retain
/ -release
自己。)
所以,你想声明块属性copy
,因此块时该属性设置,避免悬空指针到一个基于堆栈的块复制语义。
“最佳做法”你是指简单地说,“看到作为ARC是要不管你写什么在这里奇迹般地复制你的块,这是最好的,你明确写入‘复制’,以免混淆后人看你的代码。”
说明如下:
通常情况下,你不应该需要复制(或保留)块。 您只需要在您所期望的块中,它被宣布为范围的破坏后可以用来进行复印。 复制移动的块的堆。
-blocks编程主题:使用块,复制块
显然,在财产分配块意味着它可能它是在已被破坏申报范围后使用。 因此,根据块编程主题该块应该被复制到与该堆Block_copy
。
但ARC需要照顾这个要求:
块“只是工作”当你通过块了在ARC模式堆栈,如在回报。 你不必调用块拷贝了。
- 过渡到ARC
请注意,这不是关于retain
语义块。 有根本没有办法不被移动离开(即将要被弹起)堆栈和到堆存在的块的上下文。 所以不管什么属性,你有资格的@property
用,ARC仍在复制块。