Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS Designated Initializers : Using NS_DESIGNATED_INITIALIZER

We have this new macro being introduced in XCode 6 : NS_DESIGNATED_INITIALIZER

I searched on the net, but couldn't really find any good documentation as to how to use this.

Syntactically, we can use it like :

- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER; 

But what are the possible advantages of marking an initializer with this macro, and also what are the things we should be looking at when using this ?

I am mainly interested in the use cases of this macro. Any links / documentation would be appreciated.

like image 897
Mehul Parmar Avatar asked Oct 03 '14 19:10

Mehul Parmar


People also ask

What is the difference between convenience and designated initializer?

A designated initializer fully initializes all properties introduced by that class and calls an appropriate superclass initializer to continue the initialization process up to the superclass chain. Convenience initializers are secondary, supporting initializers for a class.

What does NS_ DESIGNATED_ initializer do?

The designated initializer guarantees the object is fully initialised by sending an initialization message to the superclass. The implementation detail becomes important to a user of the class when they subclass it.

What are Initializers in Swift?

An initializer is a special type of function that is used to create an object of a class or struct. In Swift, we use the init() method to create an initializer. For example, class Wall { ... // create an initializer init() { // perform initialization ... } }


1 Answers

The use of NS_DESIGNATED_INITIALIZER is nicely explained in http://useyourloaf.com/blog/2014/08/19/xcode-6-objective-c-modernization.html:

The designated initializer guarantees the object is fully initialised by sending an initialization message to the superclass. The implementation detail becomes important to a user of the class when they subclass it. The rules for designated initializers in detail:

  • A designated initializer must call (via super) a designated initializer of the superclass. Where NSObject is the superclass this is just [super init].
  • Any convenience initializer must call another initializer in the class - which eventually leads to a designated initializer.
  • A class with designated initializers must implement all of the designated initializers of the superclass.

As an example, if your interface is

@interface MyClass : NSObject @property(copy, nonatomic) NSString *name; -(instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER; -(instancetype)init; @end 

then the compiler checks if the (convenience) initializer init calls the (designated) initializer initWithName:, so this would cause a warning:

-(instancetype)init {     self = [super init];     return self; } 

and this would be OK:

-(instancetype)init {     self = [self initWithName:@""];     return self; } 

In Swift the rules about designated and convenience initializers are even more strict, and if you mix Objective-C and Swift code, marking the designated Objective-C initializers helps the compiler to enforce the rules.

For example, this Swift subclass would cause an compiler error:

class SwClass: MyClass {     var foo : String     init(foo : String) {         self.foo = foo         super.init()     } } 

and this would be OK:

class SwClass: MyClass {     var foo : String     init(foo : String) {         self.foo = foo         super.init(name: "")     } } 
like image 50
Martin R Avatar answered Sep 22 '22 02:09

Martin R