Подтвердить что ты не робот

Внедрить собственный сеттер или использовать KVO?

Короче говоря, при изменении значения свойства мне нужно обновить некоторую логику в моем коде, например:

- (void)setProp:(NSString *)theProp
{
  if (prop != theProp){
    [prop release];
    prop = [theProp copy];
    [self myLogic];
  }
}

или

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
  if ([keyPath isEqualToString:@"prop"]){
    [self myLogic];
  }  
}

Какой лучший способ и ПОЧЕМУ?

EDIT: я префект второй способ, потому что я не знаю, что компилятор будет генерировать директиву @synthesize для меня, я решил полагать, что компилятор более умнее, чем моя реализация сеттера, поэтому я не буду нарушать что-то.

4b9b3361

Ответ 1

Жесткий вызов, ИМХО оба варианта сосут.

Первый заставляет вас писать собственный сеттер, в котором много шаблонов. (Не говоря уже о том, что вы должны помнить, чтобы также отключать уведомления KVO с willChangeValueForKey: и didChangeValueForKey:, если вы хотите, чтобы KVO для рассматриваемого свойства работал.)

Второй вариант также довольно тяжелый, и вашей реализации недостаточно. Что делать, если ваш суперкласс также имеет некоторые KVO? Вы должны вызвать super где-нибудь в обработчике. Если нет, вы уверены, что ваш суперкласс не изменится? (Подробнее о KVO в связанном вопросе.)

Иногда вы можете обойти проблему, используя другие методы, такие как привязки (если вы на Mac) или обычные уведомления (вы можете опубликовать уведомление о том, что модель изменилась, и все заинтересованные стороны должны обновиться).

Если у вас много перерасчетов, подобных этому, и не могу найти лучшего способа, я бы попытался написать суперкласс с лучшей поддержкой наблюдения, с таким интерфейсом:

[self addTriggerForKeyPath:@"foo" action:^{
    NSLog(@"Foo changed.");
}];

Это потребует больше работы, но оно будет тщательно разделять ваши классы, и вы сможете решить все проблемы, связанные с KVO, на одном месте. Если для этого не достаточно повторно рассчитанных свойств, я обычно использую первое решение (настраиваемый сеттер).

Ответ 2

Первый фрагмент - это путь, если вы заинтересованы в изменениях в одном и том же объекте. Вам нужно всего лишь использовать второй, если вы заинтересованы в изменениях в других объектах, используя его для наблюдения self является излишним.

Ответ 3

В вашем случае лучшим вариантом является добавление логики внутри сеттера. Реализация вашего сеттера верна, если объявление свойства является чем-то вроде

@property (неатомный, копия) YCYourClass * prop;

KVO обычно используется при проверке изменений свойств внешних объектов.

NSNotifications лучше подходят для информирования о событиях.