Maybe this will answer your questions:
- An
init
method is just a method like any other, there is nothing special about them per se;
- Method parameters are local variables which are assigned an initial value, that value being the one given in the call;
self
is a hidden method parameter, a value for it is passed in the call as with all other parameters;
- The result of the method is implicitly marked with the
ns_returns_retained
attribute; and finally
- The
self
parameter is implicitly marked with the ns_consumed
attribute.
The attributes mentioned effect how ARC manages the references returned (ns_returns_retained
) by, or passed to (ns_consumes
), a method. These attributes can be explicitly applied to any method.
The attribute ns_returns_retained
is applied implicitly to methods in the alloc
, copy
, init
, mutableCopy
, and new
families; while ns_consumes
is implicitly applied to the hidden self
parameter of init
methods.
The ns_consumes
attribute is the only "unusual" feature of init
methods. It tells ARC that the method being called takes ownership of the passed object reference, and hence is responsible for releasing it when required. So in the common statement found in init
methods, a call to the superclass init
method:
self = [super init];
the current reference stored in self
is passed to the called method along with the callers ownership of that reference. When the result of the call is assigned back to self
ARC does not need to relinquish ownership (aka "release") the old reference stored there - ownership was already passed to the called method - or take ownership (aka "retain") of the new reference - as the called transfers its ownership back to the caller.
The above allows an init
method to return a different reference than the one it was passed, and releasing the one it was passed. This feature is not commonly used in user classes but a number of common system classes, e.g. NSString
and NSNumber
, take advantage to reduce the number of objects needed.
The above sounds more complicated than it is! If you have specific questions then ask new specific questions as @MichaelDautermann suggests in the comments.
HTH
Addendum
In response to comments maybe the following will help. All code typed directly on an iPad, expect errors!
How does the following method work?
- (NSString *) doSomething:(NSString *)aLocal
{
aLocal = [super aLocal];
return aLocal;
}
In the call:
NSString *someResult = [someObjectRef doSomething:someLocalVariable];
where someObjectRef
is a variable holding a reference to an object that declares the above method, and someLocalVariable
holds a reference to a string.
In outline it is:
- a new method invocation is created along with its local variable
aLocal
- the reference stored in the callers
someLocalVariable
is copied (it's value not the object it references) and stored in aLocal
- the statements of the method are executed
- the first statement is a call to the same method implemented in the super class, the value of the reference in
aLocal
is passed to this method, and the reference returned by the call is stored into aLocal
- replacing the reference previously stored there.
- the second statement returns the value of the reference stored in
aLocal
as the method result, and that reference is stored into the caller's someLocalVariable
.
None of that should be surprising, and the reference return is probably not the reference passed in (it could be, we've no idea what the inherited doSomething
method does, it may just return what it was passed).
Now all you have to understand is that self
is an implicitly passed parameter. What that means is the above method is effectively declared as:
- (NSString *) doSomething:(NSString *)aLocal selfRef:(instancetype)self
and Objective-C automatically supplies the reference passed as selfRef
and stored into the method's local variable self
.
Finally changing the name of doSomething
to, say, initAndDoSomething
changes the way ARC automatically handles the references passed as self
and the one returned to ensure no unwanted objects get left lying around - this is done by implicitly adding the attributes mentioned in the original answer.
That's it, init
methods are just methods. Don't think of them as special, it inflates their ego ;-)
HTH