收到一个KVC更改的两个KVO通知

17
我正在使用KVC/KVO为大学项目创建一个自定义绑定实现(需要自定义,因为我想做超出绑定能力的事情,包括在iOS上运行)。我有一个“绑定控制器”,它在对象的多个键上注册了KVO通知(使用addObserver:forKeyPath:options:context:),并且我确实收到了通知。然而,每次更改我都会收到两个通知。我有一个解决方法的想法,但我更愿意找出为什么会发生这种情况并进行更正!有人有任何想法吗?我确定只注册了每个通知一次,取消注册一次会导致两个通知都停止。谢谢。
编辑:我有一个代码请求,所以我会放一些代码。它现在还很简陋,基本上还是一个概念验证,所以请见谅。这是我正在观察的属性之一(我知道这有点奇怪,但是这个类基本上将NSManagedObject的某些属性公开为自身的属性):
- (void)setName:(NSString *)name
{
    [self willChangeValueForKey:@"name"];
    [contact setFirstName:name];
    [self didChangeValueForKey:@"name"];
}
这是我用来观察该属性的代码(确认只运行一次,且仅在单个位置运行):
[viewModel addObserver:self
            forKeyPath:@"name"
               options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial)
               context:viewController];
任何更改该属性的后续调用, 例如:
viewModel.name = @"Joe";
[viewModel setName: @"Joe"];
[viewModel setValue: @"Joe" forKey: @"name"];

这将导致该方法:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

需要两次调用,每次使用相同的参数。

2个回答

22

你正在做这件事:

- (void)setName:(NSString *)name
{
    [self willChangeValueForKey:@"name"];
    [contact setFirstName:name];
    [self didChangeValueForKey:@"name"];
}

根据听起来的情况,您正在使用非NSManagedObject的子类。这意味着Cocoa将尝试自动为您发送KVO通知。你正在补充它,也在发自己的通知。解决方案:

  • 重写+automaticallyNotifiesObserversForKey: 方法并返回 NO
  • 将您的方法更改为:

    - (void)setName:(NSString *)name { [contact setFirstName:name]; }


太棒了,看起来问题已经解决了。我不知道如果你自己实现访问器,Cocoa会自动发送这些事件。谢谢! - extremeboredom

1
也许在你的 addObserver 调用中加入一个 NSLog,以查看是否添加了两个观察者。

我已经检查过了,addObserver调用只存在于一个方法中,而且我确认该方法只运行一次。 - extremeboredom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接