NS_DESIGNATED_INITIALIZER

什么是特定构造方法:

后面带有NS_DESIGNATED_INITIALIZER的方法,就是特定构造方法

- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;

注意点:

  • 子类如果重写了父类的【特定构造方法】,那么必须用super调用父类的【特定构造方法】,不然会出现警告
警告信息:Designated initializer missing a 'super' call to a designated initializer of the super class
意思:【特定构造方法】缺少super去调用父类的【特定构造方法】
  • 为什么要使用特定构造方法
    Objective-C 中主要通过NS_DESIGNATED_INITIALIZER宏来实现指定构造器的。这里之所以要用这个宏,往往是想告诉调用者要用这个方法去初始化(构造)类对象。
  • 如果在项目中自定义构造方法使用了NS_DESIGNATED_INITIALIZER,会出现以下警告
    如果用了NS_DESIGNATED_INITIALIZER,那么警告中出现init还是initWithNibName或是其它,取决于你的继承的父类类型。
Method override for the designated initializer of the superclass '-init' not found
Method override for the designated initializer of the superclass '-initWithNibName:bundle:' not found
  • 怎样避免使用NS_DESIGNATED_INITIALIZER产生的警告
    如果子类指定了新的初始化器,那么在这个初始化器内部必须调用父类的Designated Initializer。并且需要重写父类的Designated Initializer,将其指向子类新的初始化器。
// .h
- (instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER;

// .m
- (instancetype)init {

    return [self initWithName:@""];
}

- (instancetype)initWithName:(NSString *)name {

    self = [super init];

    if (self) {
        // do something
    }

    return self;
}
  • 更好的做法:
    如果定义NS_DESIGNATED_INITIALIZER,大多是不想让调用者调用父类的初始化函数,只希望通过该类指定的初始化进行初始化,这时候就可以用NS_UNAVAILABLE宏。
    如果调用者使用init 初始化,编译器就会给出一个编译错误。使用NS_UNAVAILABLE后,就不需要在.m中重写父类初始化函数了。如果要允许调用者使用init就需要在.m中重写父类的初始化函数,如上提到的,否则就会报警告。
// .h
- (instancetype)init NS_UNAVAILABLE;

- (instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER;
  • 避免使用new
    如果使用new来创建对象的话,即使init被声明为NS_UNAVAILABLE,也不会收到编译器的警告和错误提示了。

参考文献:

http://www.saitjr.com/ios/ios-ns_unavailable-ns_designated_initializer.html

你可能感兴趣的:(NS_DESIGNATED_INITIALIZER)