正确使用NS_DESIGNATED_INITIALIZER

文章目录
  1. 1. 为什么会提到NS_DESIGNATED_INITIALIZER
  2. 2. 正确使用NS_DESIGNATED_INITIALIZER
    1. 2.1. 为什么要用NS_DESIGNATED_INITIALIZER
    2. 2.2. 怎样避免使用NS_DESIGNATED_INITIALIZER产生的警告
    3. 2.3. 更好的做法
  3. 3. 避免使用new
  • 参考链接
  • 本文结束了下指定初始化函数,本文完全转载自 正确使用NS_DESIGNATED_INITIALIZER

    为什么会提到NS_DESIGNATED_INITIALIZER

    ============================================================

    最近在清理项目警告,遇到了“Method override for the designated initializer”的警告,全称为:

    • 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 声明的初始化方法,如下:

    1
    - (instancetype)initWithPurchaseService:(HTLPrepayPurchaseService *)service NS_DESIGNATED_INITIALIZER;

    如果用了NS_DESIGNATED_INITIALIZER,那么警告中出现init、initWithNibName或是其它,取决于你的继承的父类类型:

    UIViewController

    • Method override for the designated initializer of the superclass ‘-initWithNibName:bundle:’ not found

    • Method override for the designated initializer of the superclass ‘-initWithCoder:’ not found

    UIView

    • Method override for the designated initializer of the superclass ‘-initWithFrame:’ not found

    • Method override for the designated initializer of the superclass ‘-initWithCoder:’ not found

    NSObject

    • Method override for the designated initializer of the superclass ‘-init’ not found

    正确使用NS_DESIGNATED_INITIALIZER

    为什么要用NS_DESIGNATED_INITIALIZER

    Objective-C 中主要通过NS_DESIGNATED_INITIALIZER宏来实现指定构造器的。这里之所以要用这个宏,往往是想告诉调用者要用这个方法去初始化(构造)类对象

    怎样避免使用NS_DESIGNATED_INITIALIZER产生的警告

    如果子类指定了新的初始化器,那么在这个初始化器内部必须调用父类的Designated Initializer。并且需要重写父类的Designated Initializer,将其指向子类新的初始化器。

    如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    - (instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER;


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


    - (instancetype)initWithName:(NSString *)name
    {
    self = [super init];
    if (self)
    {
    // do something
    }
    return self;
    }

    更好的做法

    如果定义NS_DESIGNATED_INITIALIZER,大多是不想让调用者调用父类的初始化函数,只希望通过该类指定的初始化进行初始化,这时候就可以用NS_UNAVAILABLE宏。

    如下:

    1
    2
    - (instancetype)init NS_UNAVAILABLE;
    - (instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER;

    如果调用者使用init 初始化,编译器就会给出一个编译错误。使用NS_UNAVAILABLE后,就不需要在.m中重写父类初始化函数了。如果要允许调用者使用init就需要在.m中重写父类的初始化函数,如上提到的,否则就会报警告。

    避免使用new

    如果使用new来创建对象的话,即使init被声明为NS_UNAVAILABLE,也不会收到编译器的警告和错误提示了。

    参考链接

    1. iOS Designated Initializers : Using NS_DESIGNATED_INITIALIZER