如何在不触发KVO的情况下设置值

问题描述 投票:0回答:3

我使用以下代码在对象上添加 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];
objective-c key-value-observing
3个回答
6
投票

如果你想这样做,你的设计就被破坏了。键值观察的要点是,有人想知道字段何时发生变化,因此他们注册通知。遵守键值观察的要点是,您可以对系统的其余部分如何与您交互保持开放的选择。

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

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

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

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

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


6
投票

Core Data 实现了

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

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

但是,在执行此操作时,应该在聚合通知的背景下,最终通过手动

willChangeValueForKey:
didChangeValueForKey:
通知观察者。


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];
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.