考虑 ARC 如何处理变量- 每个引用变量都有一个模式(隐式或显式):strong、weak等。这种模式让 ARC 知道如何处理对该变量的读取和写入;例如,对于强变量,读取不需要额外的操作,而写入需要在变量被新引用替换之前释放变量中的现有引用。ARC 需要知道任何变量的模式才能发挥作用。
现在考虑本身通过引用传递的变量,例如,对于您,execute
您将按照以下方式进行调用:
NSError *myError = nil;
...
[someObject execute:&myError]; // pass the variable itself by reference, not the variables value
并且正文execute
将包含一个分配,如下所示:
- (void)execute:(NSError * __autoreleasing *)error
{
...
if (error != NULL)
*error = [NSError ...]; // assign indirectly via the reference to a variable
...
}
现在对于间接赋值,ARC 需要知道被引用变量的模式,这样它就知道如何读写。这就是__autoreleasing
声明中的内容,它告诉 ARC 它已经传递了对模式为autoreleasing的变量的引用,并告诉 ARC 如何读取和写入变量的内容。将假定删除__autoreleasing
和默认模式,在这种情况下,我建议显式肯定是好的。
自动释放模式意味着变量包含一个不属于自己的引用,如果需要,读取应该保留,而写入可以只写入。它主要用于通过引用传递的变量。
您可能会注意到,在上面的示例中,变量myError
具有强模式(隐式),但它作为自动释放通过引用传递- 编译器通过引入临时自动释放变量、复制而不保留当前引用myError
并传递作为参数的临时引用execute:
。调用返回后,编译器会从临时 to 进行正常分配myError
,这会导致释放任何旧引用并保留返回的引用。
有关更多详细信息,请参阅Apple 过渡到 ARC 发行说明
跟进评论
问:是__autoreleasing
隐式设置的吗?
A:Apple 的文档并不具体,但Clang 文档说它是隐含的间接参数。如上所述,我建议明确,清晰是一件好事™。
问:位置重要吗?
A:是的,也不是……这是一个 C 声明,是问答题(“以下声明是什么……”)。限定符应该在两个星号之间,因为它是一个指向 object 的(类型变量)自动释放指针的指针,但 Apple 声明编译器是“宽容的”,但没有具体说明它宽容的内容。安全起见,把它放在正确的地方。
问:在做间接分配之前,你不应该测试error
存在吗?NULL
A:当然你应该,在你做间接之前的某个地方。显示的代码只是一个大纲,这些细节被...
's 省略和覆盖了。然而,由于多年来它已经被提出了几次,也许我省略了太多,所以if
添加了一个合适的。