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.
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.
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.
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 ... } }
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: "") } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With