Overriding init in subclass

2019-01-31 15:34发布

问题:

In Objective-C, is it necessary to override all inherited constructors of a subclass to add custom initialization logic?

For example, would the following be correct for a UIView subclass with custom initialization logic?

@implementation CustomUIView

- (id)init {
    self = [super init];
    if (self) {
        [self initHelper];
    }
    return self;
}

- (id)initWithFrame:(CGRect)theFrame {
    self = [super initWithFrame:theFrame];
    if (self) {
        [self initHelper];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)decoder {
    self = [super initWithCoder:decoder];
    if (self) {
        [self initHelper];
    }
    return self;
}

- (void) initHelper {
    // Custom initialization
}

@end

回答1:

Every Cocoa Touch (and Cocoa) class has a designated initializer; for UIView, as stated in this documentation, that method is initWithFrame:. In this particular case, you'll only need to override initWithFrame; all other calls will cascade down and hit this method, eventually.

This goes beyond the scope of the question, but if you do end up creating a custom initializer with extra parameters, you should make sure to the designated initializer for the superclass when assigning self, like this:

- (id)initWithFrame:(CGRect)theFrame puzzle:(Puzzle *)thePuzzle title:(NSString *)theTitle {
    self = [super initWithFrame:theFrame];
    if (self) {
        [self setPuzzle:thePuzzle];
        [self setTitle:theTitle];
        [self initHelper];
    }
    return self;
}


回答2:

In general you should follow the designated initializer convention. The designated initializer is the init, that covers the initialization of all instance variables. The designated initializer is also the method that is called by other init methods of a class.

Apple's documentation about designated initializers.

initWithFrame: is the designated initializer of the NSView class. Apple's Cocoa documentation always explicitly mentions the designated initializer of a class.

initWithCoder: is discussed here on SO.



回答3:

In case of using Interface Builder, the one is called is :

- (id)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
       //do sth
    }
    return self;
}