In which situations do we need to write the __autoreleasing ownership qualifier under ARC?
我正在努力完成这个难题。
但是,究竟
1 | - (BOOL)save:(NSError**); |
或
1 2 | NSError *error = nil; [database save:&error]; |
必须按照以下方式声明:
1 | - (BOOL)save:(NSError* __autoreleasing *); |
但这太含糊了,我想完全理解为什么。我找到的代码片段把"自动租赁"放在两颗星之间,这对我来说很奇怪。类型是
另外,在其他情况下,我必须依赖于
你说得对。如官方文件所述:
__autoreleasing to denote arguments that are passed by reference (id *) and are autoreleased on return.
所有这些在弧过渡指南中都有很好的解释。
在您的nserrror示例中,声明意味着
1 | NSError * e = nil; |
将转换为:
1 | NSError * __strong error = nil; |
调用
1 | - ( BOOL )save: ( NSError * __autoreleasing * ); |
然后,编译器必须创建一个临时变量,设置为
1 2 | NSError * error = nil; [ database save: &error ]; |
将转换为:
1 2 3 4 | NSError * __strong error = nil; NSError * __autoreleasing tmpError = error; [ database save: &tmpError ]; error = tmpError; |
您可以通过直接将错误对象声明为
跟进Macmade的回答和自豪会员在评论中的后续问题(也会将此作为评论发布,但超过了最大字符数):
这就是为什么uu autoreleasing的变量限定符放在两颗星之间的原因。
首先,声明带有限定符的对象指针的正确语法是:
1 | NSError * __qualifier someError; |
编译器会原谅这一点:
1 | __qualifier NSError *someError; |
但这是不正确的。请参阅《Apple Arc Transition Guide》(Apple Arc Transition指南)(请阅读以"您应该正确地修饰变量…"开头的部分)。
要解决手头的问题:双指针不能有弧内存管理限定符,因为指向内存地址的指针是指向基元类型的指针,而不是指向对象的指针。但是,当您声明一个双指针时,arc确实想知道第二个指针的内存管理规则是什么。这就是为什么双指针变量被指定为:
1 | SomeClass * __qualifier *someVariable; |
因此,对于双nserrror指针的方法参数,数据类型声明为:
1 | - (BOOL)save:(NSError* __autoreleasing *)errorPointer; |
它的英文意思是"指向自动释放nserrror对象指针的指针"。
最终的ARC规范指出
For __autoreleasing objects, the new pointer is retained, autoreleased, and stored into the lvalue using primitive semantics.
例如,代码
1 | NSError* __autoreleasing error = someError; |
实际转换为
1 | NSError* error = [[someError retain] autorelease]; |
…这就是为什么当你有一个参数
您可以在不同的上下文中使用