Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
522 views
in Technique[技术] by (71.8m points)

objective c - 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...