在哪些情况下,我们需要在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池,并且已经自动处理了。