在某些情况下,在我查看的代码中,在 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] 可以吗?如果是,您有什么例子吗?
答案 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]
是正确的。