5

我使用以下代码在对象上添加 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];
4

3 回答 3

6

Core Data 实现setPrimitiveValue:forKey:了允许你这样做。您可以在对象中实现相同的方法。

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

然而,当这样做时,它应该在聚合通知的上下文中,观察者最终会通过手动willChangeValueForKey:didChangeValueForKey:.

于 2013-01-27T01:24:22.643 回答
5

如果你想这样做,你的设计就会被破坏。键值观察的要点是有人想知道字段何时更改,因此他们注册通知。遵守键值观察的关键在于,您对系统的其余部分如何与您进行交互保持开放的态度。

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

如您所料,Cocoa 没有任何机制来支持此类黑客攻击。它们是非常糟糕的做法,破坏了面向对象编程的整个结构。

抛开讲课不谈,您可以编写一个直接访问实例变量的自定义设置器。所以,例如

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

在系统级别,键值观察是通过创建一个新版本的属性设置器来实现的,该版本包含对真实设置器的调用,并在外部进行适当的观察者调用。因此,避免真正的二传手将避免通知。

于 2013-01-27T00:55:28.307 回答
0

您可以使用忽略标志。与用户驱动更新的文档中的想法相同。

// 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];
    }
}
于 2020-10-29T19:44:36.860 回答