Humza Choudry
Humza Choudry

Reputation: 57

clarify init method using subclass

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

Answers (1)

CRD
CRD

Reputation: 53010

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

Upvotes: 1

Related Questions