Переопределение init в подклассе

В Objective-C необходимо ли переопределить все унаследованные конструкторы подкласса, чтобы добавить настраиваемую логику инициализации?

Например, будет ли следующее правильно для подкласса UIView с настраиваемой логикой инициализации?

@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

person hpique    schedule 05.12.2010    source источник


Ответы (3)


Каждый класс Какао Touch (и Какао) имеет назначенный инициализатор; для UIView, как указано в этой документации, этот метод initWithFrame:. В этом конкретном случае вам нужно только переопределить initWithFrame; все остальные вызовы будут каскадированы и в конечном итоге попадут в этот метод.

Это выходит за рамки вопроса, но если вы в конечном итоге создаете настраиваемый инициализатор с дополнительными параметрами, вы должны убедиться в назначенном инициализаторе для суперкласса при назначении self, например:

- (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;
}
person Sam Ritchie    schedule 05.12.2010
comment
Итак, даже если я создаю CustomUIView с помощью простого init, он вызовет initWithFrame? - person hpique; 05.12.2010
comment
Это правильно. Чтобы проверить это, необходимо переопределить как init: так и initWithFrame :, установить точки останова (или операторы NSLog) в первой строке каждого из них и создать экземпляр CustomUIView с помощью init. Вы должны увидеть, что сначала выполняется init, а затем - initWithFrame :. - person Sam Ritchie; 05.12.2010
comment
Важно помнить, что если объект создается из NIB, вызывается initWithCoder:, а НЕ initWithFrame:. - person Pascal; 29.05.2011
comment
@Pascal, это хороший аргумент и, вероятно, его следует отредактировать в ответе из документа, на который есть ссылка в ответе о initWithFrame: Если вы используете Interface Builder для разработки своего интерфейса, этот метод не вызывается, когда ваши объекты представления впоследствии загружаются из файла пера. - person pauloya; 08.02.2012
comment
Дополнительная цитата из Документы Apple о загрузке представлений из файлов ресурсов: Пользовательские представления в OS X получают сообщение initWithFrame:, а Пользовательские представления в iOS - нет используйте для инициализации метод initWithFrame :. - person MDJ; 28.04.2013
comment
Итак, с комментариями @Pascal принятый ответ Сэма неверен. Поскольку вы не можете полагаться на соглашение для конструкторов, вероятно, будет меньше времени предположить, что вы должны переопределить их все, чтобы ваш init запускался каждый раз. - person gdbj; 29.04.2014
comment
@GregoryJohnson Не обязательно все из них; initWithCoder: особенный, он входит в категорию NSCoding. Вы можете переопределить назначенный инициализатор, initWithFrame: в данном случае PLUS initWithCoder:. - person Pascal; 29.04.2014

В случае использования Interface Builder он называется:

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

В общем, вы должны следовать назначенному соглашению об инициализаторах. Назначенный инициализатор - это init, который охватывает инициализацию всех переменных экземпляра. Назначенный инициализатор - это также метод, который вызывается другими методами инициализации класса.

Apple документация по назначенным инициализаторам.

initWithFrame: - назначенный инициализатор класса NSView. В документации Apple Cocoa всегда явно упоминается назначенный инициализатор класса.

initWithCoder: обсуждается здесь, на SO .

person Thomas Zoechling    schedule 05.12.2010