在哪些情况下,我们需要在ARC下编写__autoreleasing所有权限定符?

我正在努力完成这个难题。

__strong是NSObject,NSString等所有Objective-C可保留对象指针的默认值。这是一个强有力的参考。 ARC在范围的末尾用“ -release平衡它。

__unsafe_unretained等于旧的方式。 它用于弱指针而不保留可保留对象。

__weak就像__unsafe_unretained只不过它是一个自动调零的弱引用,意味着一旦被引用的对象被释放,指针将被设置为nil。 这消除了悬挂指针和EXC_BAD_ACCESS错误的危险。

但是,究竟是什么__autoreleasing好? 当我需要使用这个限定符时,我很难find实际的例子。 我相信这只适用于需要指针指针的函数和方法,例如:

 - (BOOL)save:(NSError**); 

要么

 NSError *error = nil; [database save:&error]; 

根据ARC,必须这样声明:

 - (BOOL)save:(NSError* __autoreleasing *); 

但是这太模糊了,我想完全理解为什么 。 代码片段,我发现__autoreleasing在两颗星之间,这看起来很奇怪。 这个types是NSError** (一个指向NSError**的指针),那么为什么要在这个星号之间放置__autoreleasing而不是简单地在NSError**

另外,还可能有其他的情况,我必须依靠__autoreleasing

你是对的。 正式文件解释说:

__autoreleasing表示通过引用(id *)传递的参数,并在返回时自动释放。

所有这些在ARC转换指南中都有很好的解释。

在你的NSError例子中,声明意味着__strong ,隐含的意思是:

 NSError * e = nil; 

将转化为:

 NSError * __strong error = nil; 

当你调用你的save方法时:

 - ( BOOL )save: ( NSError * __autoreleasing * ); 

编译器将不得不创build一个临时variables,设置为__autoreleasing 。 所以:

 NSError * error = nil; [ database save: &error ]; 

将转化为:

 NSError * __strong error = nil; NSError * __autoreleasing tmpError = error; [ database save: &tmpError ]; error = tmpError; 

您可以通过直接声明错误对象为__autoreleasing来避免这种情况。

跟着Macmade的回答和骄傲的成员在评论中的后续问题,(也将此作为评论发布,但超过了最大字符数):

这就是为什么__autoreleasing的variables限定符放在两颗星之间的原因。

前言中,用限定符声明对象指针的正确语法是:

 NSError * __qualifier someError; 

编译器会原谅这个:

 __qualifier NSError *someError; 

但这是不正确的。 请参阅Apple ARC转换指南 (请阅读“您应该正确修饰variables…”部分)。

为了解决手头的问题:双指针不能有ARC内存pipe理限定符,因为指向内存地址的指针是指向基本types的指针,而不是指向对象的指针。 但是,当你声明一个双指针时,ARC确实想知道第二个指针的内存pipe理规则是什么。 这就是为什么双指针variables被指定为:

 SomeClass * __qualifier *someVariable; 

所以在一个double NSError指针的方法参数的情况下,数据types被声明为:

 - (BOOL)save:(NSError* __autoreleasing *)errorPointer; 

用英文说“指向__autoreleasing NSError对象指针”。

最终的ARC规范说明了这一点

对于__autoreleasing对象,新指针被保留,自动释放,并使用原语语义存储到左值中。

所以例如,代码

 NSError* __autoreleasing error = someError; 

实际上被转换为

 NSError* error = [[someError retain] autorelease]; 

…这就是为什么当你有一个参数NSError* __autoreleasing * errorPointer ,被调用的方法将把错误分配给*errorPointer ,并且上面的语义将会进入。

你可以在不同的上下文中使用__autoreleasing来强制一个ARC对象进入autorelease池,但这不是非常有用,因为ARC似乎只在方法返回时使用autorelease池,并且已经自动处理了。