As per Transitioning to ARC Release Notes:
__autoreleasing is used to denote arguments that are passed by reference (id *) and are autoreleased on return.
For example:
-(BOOL)performOperationWithError:(NSError * __autoreleasing *)error;
But what are the advantages of the above comparing to:
-(BOOL)performOperationWithError:(NSError * __strong *)error;
Update:
Several answers refer to the temp var trick compiler does to deal with the mismatch between var and argument as the advantage of __autoreleasing. I don’t see why compiler can not do the same trick for __strong argument. I mean, for a __weak var and __strong argument, compiler can similarly do this:
NSError * __weak error;
NSError * __strong tmp = error;
BOOL OK = [myObject performOperationWithError:&tmp];
error = tmp;
if (!OK) {
// Report the error.
}
Compiler knows -(BOOL)performOperationWithError:(NSError * __strong *)error; returns a strong reference(+1) so it handles it just like any new-family method. Since tmp lives in the same scope as error, compiler can reasonably keep it alive as long as error so the __weak reference(error) is now supported by a __strong reference(tmp) and will not be nullified until the end of the scope.
tl;dr
Implicitly converting a
__weakobject to a__strongobject in this case would alter the semantic of the program, something that a compiler should never do.The scenario
Let’s take an example
In such a case the
errorlocal variable is automatically inferred by ARC as__strong.At the same time the
errorargument ofis of type
NSError * __autoreleasing *.Please note that in any case ARC will infer parameters passed by reference (
id *) as being of typeid __autoreleasing *, so the above signature is equivalent tounder ARC.
Therefore we have a mismatch since we are passing a
__strongannotated variable to a method expecting an__autoreleasingargument.Under the hood
In our example then the compiler will address such mismatch by creating a local
__autoreleasing tmpvariable.The code becomes
An alternative
Let’s now pretend that we can change the signature of
performOperationWithError:.If we want to avoid the "compiler trick" which uses the
tmpvariable, we can declare our signature asWe have a
__strongvariable and we are now passing it to a method expecting a__strongargument, so we just eliminated the mismatch.Looks good, why not always declare
__strongarguments?One reason is that declaring the argument as
__autoreleasingwill make the method to accept even a__weakreference.It does not make much sense in the current example, but there could be cases in which we’d like to pass a
__weakvariable by reference and declaring__autoreleasing(or leaving the ARC to infer it) will allow us to do so.ARC will apply the same trick seen above, creating a
__autoreleasing tmpvariable.Conclusion
The mechanism presented so far goes under the name of pass-by-writeback.
Such mechanism has been designed to work with
__autoreleasing,__strongand__weakvariables, so that the programmer can safely rely on the type inference made by the compiler and not care too much about annotating variables around.Declaring a
id __strong *argument may make sense in some cases, but in general it could lead to unexpected errors generated by the compiler.My advice here is: "let the compiler do his magic and you’ll be good"
Update
Telling the compiler to handle in an
__autoreleasingfashion the management of either a__strongor__weakvariable it’s ok since it basically means: "Please, compiler, do the right thing automatically".That’s why the trick seen above will work without issues.
On the other hand, if you declare a variable as
__weakyou presumably have a good reason for doing so and the last thing you want is to have it implicitly retained when you clearly specified otherwise. That would radically change the semantic of the piece of code you’ve written, therefore the compiler won’t do that (thank God!).In other words
__weak–>__autoreleasinggood__strong–>__autoreleasinggood__weak<–>__strongwrong!