Reputation: 57
Now i have had this problem clouding my mind for quite sometime and i really need someone to clarify this for me.
1) what is a unique identifier that causes the init method to return a different object other than the one you were initially trying to allocate with the call? .. What should you do in such a case?
2) When a designated initializer from one class assuming that class has more than one method, invokes the designated initializer in its parent class consequently invoking NSObject's init method; what exactly is happening when the parent class init method is invoked? what is "self" in that method explicitly referencing to, as well as the "self" returned from its root class?
Upvotes: 0
Views: 64
Reputation: 53010
Maybe this will answer your questions:
init
method is just a method like any other, there is nothing special about them per se;self
is a hidden method parameter, a value for it is passed in the call as with all other parameters;ns_returns_retained
attribute; and finallyself
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:
aLocal
someLocalVariable
is copied (it's value not the object it references) and stored in aLocal
aLocal
is passed to this method, and the reference returned by the call is stored into aLocal
- replacing the reference previously stored there.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
Upvotes: 1