Где инициализировать пользовательский UIView, созданный в Interface Builder? - PullRequest
11 голосов
/ 02 января 2011

У меня есть подкласс UIView, который создается в файле XIB.Мне нужно сделать некоторую инициализацию (установить некоторые переменные и создать подпредставление).

Однако я не всегда создаю экземпляр этого представления через Interface Builder.Я делаю это тоже программно.В обоих случаях инициализация должна быть одинаковой.

Мой назначенный инициализатор - initWithValues:.

Вопрос в том; где я могу выполнить инициализацию?

Так как я должен выполнить это в 2 разных местах, я решил, что мне нужно реорганизовать его в отдельный метод initialize (или что-то подобное)и вызвать его из initWithValues:.

Но при загрузке из IB вызываются и initWithCoder:, и awakeFromNib.Из какого метода я должен вызвать initialize?Или мне нужно позвонить initWithValues: с initWithCoder: и ничего не делать в awakeFromNib?

Ответы [ 3 ]

17 голосов
/ 02 января 2011

Вы должны использовать initWithFrame: при инициализации представлений (так как это назначенный инициализатор).Следовательно, если у вас есть initWithValues:, убедитесь, что вы вызываете initWithFrame: с него.

Что-то подобное должно работать для инициализации:;)

- (void)initialize{
     //init your ivars here
}

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

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

Я собирался добавить ещеобъяснение, но ответ mplappert достаточно ясен.При необходимости используйте awakeFromNib.

10 голосов
/ 02 января 2011

Это зависит от того, что вам нужно инициализировать.Как только вызывается awakeFromNib, устанавливаются все выходы и соединения действий вашего представления, что не имеет место в initWithCoder:.Поэтому, если вам нужно положиться на эти соединения, используйте awakeFromNib.В противном случае вы можете безопасно выполнить всю вашу инициализацию в initWithCoder:.

1 голос
/ 20 апреля 2012

К сожалению, приведенные выше ответы не учитывают следующие вещи: - (void) awakeAfterUsingCoder - и тот факт, что он вызывается после того, как что-либо создано кодером (один раз для каждого представления Xib). Я заметил, что awakeFromNib страдает от той же участи. (Причина, по которой я нашел это)

Еще одна проблема с инициализацией заключается в том, что для пользовательских представлений можно избежать initWithCoder и initWithFrame. И если они называются, ленивая загрузка (хотя это и не так важно для самих представлений), это означает, что вы «можете» изменять значения. Я полагаю, что я сделал это в initWithCoder, но если вы затем инициализируете значения в awakeFromNib, он отменяется хотя бы один раз.

Я зашел так далеко, что:

- (void) awakeFromNib (or didMoveToSuperView);
{
    BOOL called = NO;
    if(!called)
    {
    called = YES;
    }

}

Другой метод, который я использую, - это просто вызвать необходимый инициализатор, а затем вызвать мой собственный класс или специфичный для суперкласса инициализатор.

Я тоже ищу надежное единовременное место, на которое я могу положиться. До тех пор, я надеюсь, мои головные боли спасут следующего человека примерно на час.

Steve

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...