Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 将Objective-C块定义为特性-最佳实践_Ios_Objective C_Automatic Ref Counting_Objective C Blocks - Fatal编程技术网

Ios 将Objective-C块定义为特性-最佳实践

Ios 将Objective-C块定义为特性-最佳实践,ios,objective-c,automatic-ref-counting,objective-c-blocks,Ios,Objective C,Automatic Ref Counting,Objective C Blocks,我最近遇到一个实例,其中显示了块的以下属性声明: @interface XYZObject : NSObject @property (copy) void (^blockProperty)(void); @end 此外,该条规定: 注意:应将“复制”指定为“特性”属性,因为需要复制块以在原始范围之外跟踪其捕获的状态。在使用自动引用计数时,您不必担心这一点,因为它会自动发生,但属性属性显示结果行为是最佳做法。有关详细信息,请参见块编程主题 我也读了建议,但没有发现任何相关的 我仍然很好奇为什么

我最近遇到一个实例,其中显示了块的以下属性声明:

@interface XYZObject : NSObject
@property (copy) void (^blockProperty)(void);
@end
此外,该条规定:

注意:应将“复制”指定为“特性”属性,因为需要复制块以在原始范围之外跟踪其捕获的状态。在使用自动引用计数时,您不必担心这一点,因为它会自动发生,但属性属性显示结果行为是最佳做法。有关详细信息,请参见块编程主题

我也读了建议,但没有发现任何相关的

我仍然很好奇为什么将块属性定义为“复制”是最佳实践。如果您有一个好的答案,请尝试区分ARC和MRC之间的差异(如果有)


谢谢

默认情况下,在堆栈上创建块。这意味着它们只存在于创建它们的范围内

如果您希望稍后访问它们,则必须通过向块对象发送
copy
消息将它们复制到堆中。ARC将在检测到需要在其创建的范围之外访问块时为您执行此操作。最佳做法是将任何块属性声明为副本,因为这是自动内存管理下的方式


Mike Ash阅读了有关堆栈与堆的更多信息。

默认情况下,块是在堆栈上分配的。这是一种优化,因为堆栈分配比堆分配便宜得多。堆栈分配意味着,默认情况下,当声明块的作用域退出时,该块将不再存在。因此,具有
retain
语义的块属性将导致指向不再存在的块的悬空指针

要将块从堆栈移动到堆(从而使其具有正常的Objective-C内存管理语义和延长的生存期),必须通过
[theBlock copy]
block\u copy(theBlock)
等方式复制该块。一旦进入堆,可以根据需要保留/释放该块来管理其生存期。(是的,这也适用于ARC,您不必自己调用
-retain
/
-release

因此,您希望使用
copy
语义声明块属性,以便在设置属性时复制块,避免指向基于堆栈的块的悬空指针。

您提到的“最佳实践”只需说,“鉴于无论您在此处编写什么,ARC都将神奇地复制您的块,因此最好明确地编写‘复制’,以免混淆后代查看您的代码。”

解释如下:

通常,您不需要复制(或保留)块。您只需要在销毁声明块的作用域后使用该块时进行复制。复制会将块移动到堆中。
–块编程主题:使用块、复制块

显然,将块分配给属性意味着它可以在其声明的作用域被销毁后使用。因此,根据块编程主题,应该使用
block\u copy
将块复制到堆中

但ARC会为您解决这一问题:

当您以ARC模式(如返回)向堆栈上传递块时,块“仅起作用”。您不再需要调用块复制。


请注意,这与块的
retain
语义无关。如果不将块移出(很快就会弹出),块的上下文就无法存在因此,不管你用什么属性来限定你的
@property
属性,ARC仍然会复制块。

它们是否也应该声明为week,以防你捕获self并创建一个retain循环?绝对不会,因为大多数时候属性都是块的唯一引用,所以如果property很弱,块会立即消失。嗨Joris。非常清楚,事实上,如果你简单地省略了副本,你是说它实际上会被复制吗?再次非常清楚,事实上,如果你完全省略了副本,与拥有副本相比,结果、处理和执行都是完整的完全相同?干杯。如果有人担心效率或功能,一旦一个块被复制,结果是不可变的,进一步尝试复制只会保留它,就像其他不可变的实例一样。嗨,jenmore。谢谢你的帖子。正如我上面问的,你的意见是什么……”非常清楚,事实上,如果你完全省略了副本,与拥有副本相比,结果、处理和执行都是完全相同的吗??“我们怎么看?干杯注意,对于那些只是想知道如何使用块的初学者来说:)然而,上面的两个答案似乎意味着必须这样做,而且无论如何都是自动地,通过ARC完成的——而明确包含复制的唯一原因是风格——“提醒每个人”这就是实际发生的事情。思想??