我正在努力完成这个难题。
__strong
是所有Objective-C可保留对象指针的默认值,如NSObject,NSString等。它是一个强大的引用。 ARC在范围的末尾与-release
进行平衡。
__unsafe_unretained
等于旧的方式。它用于弱指针而不保留可保留对象。
__weak
与__unsafe_unretained
类似,只是它是一个自动归零的弱引用,意味着一旦引用的对象被释放,指针就会被设置为nil。这消除了悬空指针和EXC_BAD_ACCESS错误的危险。
但__autoreleasing
到底有什么用呢?我很难找到关于何时需要使用此限定符的实际示例。我相信它只适用于期望指针指针的函数和方法,例如:
- (BOOL)save:(NSError**);
或
NSError *error = nil;
[database save:&error];
在ARC下的必须以这种方式声明:
- (BOOL)save:(NSError* __autoreleasing *);
但这太模糊了,我想完全理解为什么。我找到的代码片段将__autoreleasing放在两颗星之间,这对我来说很奇怪。类型是NSError**
(指向NSError的指针指针),那么为什么要将__autoreleasing
放在星星之间而不是简单地放在NSError**
之前?
此外,可能还有其他情况我必须依赖__autoreleasing
。
答案 0 :(得分:67)
__ autoreleasing表示通过引用传递的参数(id *)并在返回时自动释放。
所有这些都在ARC transition guide中得到了很好的解释。
在NSError示例中,声明意味着__strong
,隐含地:
NSError * e = nil;
将转变为:
NSError * __strong error = nil;
当您拨打save
方法时:
- ( BOOL )save: ( NSError * __autoreleasing * );
然后编译器必须创建一个临时变量,设置为__autoreleasing
。所以:
NSError * error = nil;
[ database save: &error ];
将转变为:
NSError * __strong error = nil;
NSError * __autoreleasing tmpError = error;
[ database save: &tmpError ];
error = tmpError;
您可以通过直接将错误对象声明为__autoreleasing
来避免这种情况。
答案 1 :(得分:33)
在评论中跟进Macmade的答案和Proud Member的后续问题,(也会将其作为评论发布,但它超出了最大字符数):
这就是__autoreleasing的变量限定符放在两颗星之间的原因。
前言,使用限定符声明对象指针的正确语法是:
NSError * __qualifier someError;
编译器会原谅这个:
__qualifier NSError *someError;
但这不正确。请参阅the Apple ARC transition guide(阅读开头的部分“你应该正确地装饰变量......”)。
解决手头的问题:双指针不能有ARC内存管理限定符,因为指向内存地址的指针是指向基本类型的指针,而不是指向对象的指针。但是,当您声明双指针时,ARC确实想知道第二个指针的内存管理规则是什么。这就是双指针变量指定为:
的原因SomeClass * __qualifier *someVariable;
因此,如果方法参数是双NSError指针,则数据类型声明为:
- (BOOL)save:(NSError* __autoreleasing *)errorPointer;
英文中的“指向__autoreleasing NSError对象指针的指针”。
答案 2 :(得分:15)
对于__autoreleasing对象,新指针被保留,自动释放,并使用原始语义存储到左值。
例如,代码
NSError* __autoreleasing error = someError;
实际上转换为
NSError* error = [[someError retain] autorelease];
...这就是为什么当你有一个参数NSError* __autoreleasing * errorPointer
时它会起作用,然后被调用的方法会将错误分配给*errorPointer
,上面的语义将会启动。
您可以在不同的上下文中使用__autoreleasing
来强制ARC对象进入自动释放池,但这并不是非常有用,因为ARC似乎只在方法返回时使用自动释放池并且已经自动处理它。