I'm trying to complete the puzzle.
__strong
is the default for all Objective-C retainable object pointers like NSObject, NSString, etc.. It's a strong reference. ARC balances it with a -release
at the end of the scope.
__unsafe_unretained
equals the old way. It's used for a weak pointer without retaining the retainable object.
__weak
is like __unsafe_unretained
except that it's an auto-zeroing weak reference meaning that the pointer will be set to nil as soon as the referenced object is deallocated. This eliminates the danger of dangling pointers and EXC_BAD_ACCESS errors.
But what exactly is __autoreleasing
good for? I'm having a hard time finding practical examples on when I need to use this qualifier. I believe it's only for functions and methods which expect a pointer-pointer such as:
- (BOOL)save:(NSError**);
or
NSError *error = nil;
[database save:&error];
which under ARC has to be declared this way:
- (BOOL)save:(NSError* __autoreleasing *);
But this is too vague and I'd like to fully understand why. The code snippets I find place the __autoreleasing inbetween the two stars, which looks weird to me. The type is NSError**
(a pointer-pointer to NSError), so why place __autoreleasing
inbetween the stars and not simply in front of NSError**
?
Also, there might be other situations in which I must rely on __autoreleasing
.
You're right. As the official documentation explains:
__autoreleasing to denote arguments that are passed by reference (id *) and are autoreleased on return.
All of this is very well explained in the ARC transition guide.
In your NSError example, the declaration means __strong
, implicitly:
NSError * e = nil;
Will be transformed to:
NSError * __strong error = nil;
When you call your save
method:
- ( BOOL )save: ( NSError * __autoreleasing * );
The compiler will then have to create a temporary variable, set at __autoreleasing
. So:
NSError * error = nil;
[ database save: &error ];
Will be transformed to:
NSError * __strong error = nil;
NSError * __autoreleasing tmpError = error;
[ database save: &tmpError ];
error = tmpError;
You may avoid this by declaring the error object as __autoreleasing
, directly.