Humza Choudry
Humza Choudry

Reputation: 57

Designated Initializer, clarify please.

Now i have had this problem clouding my mind for quite sometime and i really need someone to clarify this for me.

1) how is a designated initializer method determined by the compiler when it is called on by a subclassed init method? as it is said to be the one with the most coverage.

2) when subclassing with multiple init methods, does each class have its own designated initializer method? Answer to question 2 would add to the assist of understanding this as well.

3) When multiple classes do have a designated initializer how do the other init methods invoke the designated initializer in their class? and how come they don't invoke any other initializer as well? why the designated initializer? whats so special about it?

Upvotes: 2

Views: 911

Answers (2)

Ryan H.
Ryan H.

Reputation: 7844

In Objective-C, the designated initializer of a class is the method that's responsible for properly initializing the class to put it in an appropriate state for use. There is nothing in the code that marks it as the designated initializer, so there is usually a comment in the header file for that. It is up to the developer who is using or extending that class to figure out which method is the designated initializer (usually init or prefixed with init) and to write code accordingly. This can lead to mis-use of a class if it is not properly documented and its source code is not available and is one of the shortcomings that Swift attempts to solve. So to address your questions...

  1. A designated initializer is not determined by the compiler. A subclass should also have a designated initializer that calls the super's designated initializer at some point.
  2. Each class should clearly state (via comments or documentation) which initializer is intended to be used as the designated initializer. It is up to the developer who is using the class to make sure that the designated initializer is invoked. It is up to the developer of the class itself to ensure that the super's designated initializer is invoked as intended. However, with properly written classes, any of the init methods should invoke the designated initializer. However, it is not guaranteed by the compiler.
  3. Other init methods need to be coded appropriately to invoke the designated initializer via [self init...] or [super init...]. Again, it is up to you to figure out how a class is intended to be used and to use it or extend it appropriately.

The designated initializer is the method that does the "heavy lifting" to prepare a new instance of a class for use. Other initializers are known as convenience initializers and are typically used to provide shorter signatures with implied defaults since you can't specify default parameter values for Objective-C method signatures.

In most cases, if a class is properly written, you shouldn't really have to worry too much since all convenience initializers should end up invoking the designated one.

A lot of thought was put into this during the development of Swift and even if you don't intend to learn it, you should read up on Swift Initializers as it will give you good insight into the proper chain of initialization that you could then use to guide you in creating initializers in Objective-C.

UPDATE: Since Xcode 6, designated initializers can be marked as such, typically via the NS_DESIGNATED_INITIALIZER macro. This helps enforce properly written classes and is something that was brought back to Objective-C from Swift. Check out iOS Designated Initializers : Using NS_DESIGNATED_INITIALIZER.

Upvotes: 2

Sulthan
Sulthan

Reputation: 130102

  1. The compiler doesn't detect it in any way. For the compiler to know whether an initializer is designated or not, you have to annonate it using NS_DESIGNATED_INITIALIZER macro.

  2. If a class have an initializer, it always also has a designated initializer. It can actually have multiple designated initializers. You simply cannot have a class without designated initializers. The difference between designated and convenience is pretty simple. Designated initializers call [super init...] (calling superclass initializer) while convenience call [self init...] (calling another initializer of the same class).

  3. Convenience initializers invoke the designated ones using [self init...]. Designated initializers are not special. They are actually the most basic initializers. They do 2 things - they initialize the parent (using [super init...]) and then initialize what is needed (e.g. default values for properties etc.). Convenience initializers are the special kind - they are an extension of a designated initializer. They call the designated initializer and do something more. For example -initWithStyle: will be a designated initializer that will init an object to a specific style. -initWithStyle:andFrame: will do the same but it will also set the frame property to a specific value. If -initWithStyle:andFrame: is implemented using [self initWithStyle:... andFrame:...] then it's a convenience initializer.

Upvotes: 2

Related Questions