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: "")
}
}