如何在没有触发器KVO的情况下设置值

时间:2013-01-27 00:45:12

标签: objective-c key-value-observing

我使用以下代码在对象上添加KVO。

[self.model addObserver:self
             forKeyPath:@"userName"
                options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
                context:nil];

现在我想设置userName,如下所示。是的,它会触发KVO。

self.model.userName = @"testUser";

但是,我想在没有触发器KVO的情况下设置值。怎么做?有没有像下面这样的方法允许我这样做?

[self.model setValue:@"testUser" forKey:@"userName" isSilent:YES];

3 个答案:

答案 0 :(得分:6)

核心数据实施setPrimitiveValue:forKey:以允许您执行此操作。您可以在对象中实现相同的方法。

[self.model setPrimitiveValue:@"testUser" forKey:@"userName"];

但是,在执行此操作时,应该在聚合通知的上下文中,最终通过手动willChangeValueForKey:didChangeValueForKey:通知观察者。

答案 1 :(得分:5)

如果你想这样做,你的设计就会被打破。键值观察的关键是有人想知道字段何时发生变化,以便注册通知。遵守键值观察的关键在于,您要保持关于系统其他部分如何与您交互的选择。

你正在做的事情就是试图解决一些你不希望某人出于某种原因知道房产真正价值的问题。因此,他们认为他们正在获得更新,但实际上如果他们要检查房产,那么事实证明你是故意撒谎。

正如您所料,Cocoa没有任何支持此类黑客的机制。它们是非常糟糕的做法,打破了面向对象程序设计的整体结构。

除了讲课外,你可以编写一个直接转到实例变量的自定义setter。所以,例如。

- (void)setUserNameAndLieAboutItAsAShortSightedHack:(NSString *)newName
{
    _userName = newName;
}

在系统级别,通过创建属性setter的新版本来实现键值观察,该版本包含对真实setter的调用并在外部进行适当的观察者调用。因此,避免使用真正的setter会避免通知。

答案 2 :(得分:0)

您可以使用忽略标志。与User-Driven Updates文档中的想法相同。

// 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];
    }
}