NSError和__autoreleasing

时间:2012-11-27 15:40:57

标签: objective-c automatic-ref-counting

有人可以向我解释在以下示例代码块中使用__autoreleasing的目的吗?

- (void)execute:(NSError * __autoreleasing *)error {
    // do stuff, possibly assigning error if something went wrong
}

我删除了__autoreleasing,一切似乎仍然可以编译/运行。我开始使用obj-c后ARC,所以我从来没有真正学过/理解所有那些双下划线的东西。我已阅读ARC transition guide,但我并不完全了解他们的NSError示例。

1 个答案:

答案 0 :(得分:72)

考虑ARC如何使用变量 - 每个参考变量都有一个模式(隐式或显式):等。模式让我们的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并假定默认模式,在这种情况下我建议明确肯定是好的。

autoreleasing 模式意味着变量包含一个不拥有的引用,如果需要,读取应该保留,写入可以写入。它主要用于通过引用传递的变量。

您可能会注意到,在上面的示例中,变量myError具有模式 strong (隐式),但它通过引用传递为 autoreleasing - 编译器通过引入临时自动释放变量自动处理此问题,复制而不myError中的当前引用保留到其中,并将临时引用作为参数传递给execute:。在调用返回后,编译器执行从临时到myError的正常分配,这会导致释放任何旧引用并保留返回的引用。

有关详细信息,请参阅Apple's Transitioning to ARC Release Notes

跟进评论

问:__autoreleasing是否隐式设置?

答:好的Apple's文档并不具体,但Clang documentation表示它对于间接参数是隐含的。如上所述,我建议明确,清晰度是一件好事。

问:这个位置是否重要?

答:是的,没有......这是一个C声明,是测验问题的内容(“以下是什么声明......”)。限定符应该在两个星号之间,因为它是一个指向(对象的变量)自动释放指向对象的指针的指针,但Apple声明编译器是“宽容”而不具体说明它原谅的内容。安全地玩,把它放在正确的地方。

问:在进行间接分配之前,您是否应该测试errorNULL

答:当然你应该在你做间接之前的某个地方。显示的代码只是一个大纲,...的详细信息已被删除和覆盖。然而,由于多年来已经提高了几次,我可能已经过多了,已经添加了一个合适的if