我使用以下代码在对象上添加 KVO。
[self.model addObserver:self
forKeyPath:@"userName"
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context:nil];
现在我想设置用户名,如下所示。是的,它会触发KVO。
self.model.userName = @"testUser";
但是,我想在不触发KVO的情况下设置值。怎么做?有没有像下面这样的方法可以让我这样做?
[self.model setValue:@"testUser" forKey:@"userName" isSilent:YES];
如果你想这样做,你的设计就被破坏了。键值观察的要点是,有人想知道字段何时发生变化,因此他们注册通知。遵守键值观察的要点是,您可以对系统的其余部分如何与您交互保持开放的选择。
听起来你正在做的是试图解决一些问题,即你不希望某人出于某种原因知道财产的真实价值。所以他们认为他们正在获取更新,但实际上如果他们要检查房产,那么就会发现你是故意撒谎。
正如您所期望的,Cocoa 没有任何机制来支持此类黑客攻击。它们是非常糟糕的做法,破坏了面向对象编程的整个结构。
抛开讲授不谈,您可以编写一个直接访问实例变量的自定义设置器。所以,例如
- (void)setUserNameAndLieAboutItAsAShortSightedHack:(NSString *)newName
{
_userName = newName;
}
在系统级别,键值观察是通过创建新版本的属性设置器来实现的,该属性设置器包含对真实设置器的调用,并在外部进行适当的观察者调用。因此,避开真正的设置者就可以避免通知。
Core Data 实现了
setPrimitiveValue:forKey:
来允许您执行此操作。您可以在您的对象中实现相同的方法。
[self.model setPrimitiveValue:@"testUser" forKey:@"userName"];
但是,在执行此操作时,应该在聚合通知的背景下,最终通过手动
willChangeValueForKey:
和 didChangeValueForKey:
通知观察者。
您可以使用忽略标志。与用户驱动更新的文档中的想法相同。
// update the config object with the value the user chose.
- (IBAction)valueChanged:(UISlider *)slider{
self.ignore = YES;
self.config.sliderValue = slider.value;
self.ignore = NO;
}
// update the slider with the value from the config object.
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == kSliderKVOContext) {
if(!self.ignore){
self.slider.value = [change[NSKeyValueChangeNewKey] doubleValue];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}