语法self = [self init]在初始化方法中是否可以接受?

时间:2018-08-29 13:51:04

标签: objective-c initialization self

在某些情况下,在我查看的代码中,在 init 方法中调用了 self = [self init] 而不是 [super init] 。您认为这种语法是可以接受的,还是如果它导致使用 [self init] 的某种逻辑错误(错误的模式)的征兆?

例如(可能是另一个例子)

- (instancetype)init {
  self = [super init];
  //my code block
  return self;
}

- (instancetype)initWithDelegate:(id<MyDelegate>)delegate {
  self = [self init]; //self = [super init] is not called since "my code block" needs to be implemented
  if (self) {
    self.delegate = delegate;
  }
  return self;
}

self = [self init] 可以吗?如果是,您有什么例子吗?

1 个答案:

答案 0 :(得分:2)

上面的代码是向后的。指定的初始化程序为initWithDelegate:(因为它是初始化所有属性的初始化程序)。因此init应该呼叫initWithDelegate:

- (instancetype)init {
  self = [self initWithDelegate:nil];
  return self;
}

- (instancetype)initWithDelegate:(id<MyDelegate>)delegate {
  self = [super init];
  if (self) {
    //my code block
    self.delegate = delegate;
  }
  return self;
}

有关如何在标头中正确注释指定的初始化程序的信息,请参见iOS Designated Initializers : Using NS_DESIGNATED_INITIALIZER

当然,每个人都应该听James Dempsey sing about how this mistake impacted him

对于self = [self init]是否正确的基本问题,在大多数应用程序级代码(即库外部)中令人惊讶。指定的初始值设定项通常是采用最多参数的初始值设定项,因此,在存在多个初始值设定项时,init是最不可能的候选者。另一方面,self = [self init...]非常普遍且正确。

但是,在具有您无法控制的现有子类的代码中(例如,如果您提供了一个库),它可能仅以init开始使用,而后来又添加了其他初始化器。在这种情况下,明智的做法是指定init(这样就不必重写现有的子类),并且在那种情况下,可以肯定self = [self init]是正确的。