2013-03-18 5 views
1

Apple рекомендует НЕ использовать методы свойств в инициализаторах, однако я не уверен в том, что протокол должен следовать, если вам нужно вызвать метод из инициализатора, который также нужно вызывать из другого места, где в программе после инициализации объекта. Например, у вас есть:Разочарование шаблона в объекте C

- (id) init 
{ 
    self = [super init]; 

    if (self) 
    { 
      [self someMethod]; 
    } 

    return self; 

} 

- (void) someMethod 
{ 
    _x = 0; \\ or self.x = 0 when this method is not called from initializer 
} 

someMethod содержит кучу Ивар в нем. Проблема в том, что ее также нужно называть else, где в коде позже после инициализации объекта. Я бы хотел, чтобы аксессоры не были доступны в инициализаторе при его вызове оттуда, но я также хотел бы, чтобы они были доступны, когда someMethod вызывается из другого места. Есть ли опрятный путь вокруг этого шаблона? При использовании NSObject? При использовании UIView? При использовании UIViewController?

+1

Это не обязательное правило, а предложение. Если вы понимаете, что делаете, то совершенно правильно установить переменную свойства backing напрямую. Единственный вред приходит от этого, не задумываясь. – borrrden

+4

Если у вас нет сеттеров, которые обрабатывают другие переменные экземпляра, просто игнорируйте эту рекомендацию. –

+0

Как говорит Боррден, это всего лишь предложение. Нет никакой проблемы, чтобы использовать их внутри init. Проблема возникнет, если вы используете KVO, как правило, вы не хотите запускать ее во время инициализации или освобождения. [EDIT] или как Bauch говорит, если вы используете пользовательский сеттер/getter. – Andrea

ответ

4

Чтобы судить, можно ли проигнорировать эту рекомендацию, вы должны понять, почему эта рекомендация существует.
Основная проблема - геттеры и сеттеры, которые имеют побочные эффекты, потому что они выполняют вычисления на основе переменных экземпляра, которые не могут быть инициализированы при вызове сеттера (или получателя).

Возьмем следующий код в качестве примера:

- (id)init { 
    self = [super init]; 
    if (self) { 
     // don't do this 
     self.textColor = [UIColor blackColor]; 
     self.font = [UIFont boldSystemFontOfSize:17]; 

     // do this: 
     _textColor = [UIColor blackColor]; 
     _font = [UIFont boldSystemFontOfSize:17]; 
     [self createLayers]; 
    } 
    return self; 
} 

- (void)setFont:(UIFont *)font { 
    if (font) { 
     _font = font; 
     [self createLayers]; 
    } 
} 

- (void)setTextColor:(UIColor *)textColor { 
    if (textColor) { 
     _textColor = textColor; 
     [self createLayers]; 
    } 
} 

- (void)createLayers { 
    // calculation that will crash if font or textColor is not set 
} 

Потому что createLayers крахи если TextColor или шрифта равен нулю, используя сеттер в инициализации приведет к сбою кода.