3

可能重复:
针对单个 KVC 更改接收 2 个 KVO 通知

我对应该在哪里使用willChangeValueForKey:didChangeValueForKey:.

我有一个需要自定义设置方法的属性的对象。根据Apple 文档,我正在使用will/didChangeValueForKey:

要实现手动观察者通知,您在更改值之前调用 willChangeValueForKey: ,并在更改值之后调用 didChangeValueForKey: 。清单 3 中的示例实现了 openingBalance 属性的手动通知。

清单 3 实现手动通知的示例访问器方法

- (void)setOpeningBalance:(double)theBalance {
    [self willChangeValueForKey:@"openingBalance"];
    _openingBalance = theBalance;
    [self didChangeValueForKey:@"openingBalance"];
}

这使我的对象如下所示:

@interface cObject
@property (readwrite, nonatomic) BOOL Property;
@end

@implementation cObject
- (void)setProperty:(BOOL)Property
{
   [self willChangeValueForKey:@"Property"];
   _Property = Property;
   [self didChangeValueForKey:@"Property"];
   //Do some other stuff
}
@end

Property我困惑的根源是,如果我在 的实例上设置另一个对象来观察cObject然后调用[myObject setProperty:],我的观察者的回调函数会被命中两次。查看堆栈:第一次命中是我调用的结果didChangeValueForKey:,第二次命中是我调用的直接结果setProperty:(即我的自定义设置器没有出现在堆栈中)。

更令人困惑的是,如果我在 的其他地方更改_Property另一个函数cObject,我的观察者将不会收到通知(当然,除非我使用did/willChangeValueForKey:!)。

编辑:即使_Property我的自定义设置器没有更改,KVO 也会通知我的观察者它已更改。由此,我得出结论,KVO 被调用只是因为我调用了 setter,无论是否有任何变化......

谁能解释我的情况与文档中解释的情况有何不同?

4

1 回答 1

6

从文档。如果你想要手动,你必须覆盖它:

手动更改通知

手动更改通知可以更精细地控制通知发送给观察者的方式和时间。这有助于最大程度地减少不必要的触发通知,或将多个更改分组到单个通知中。

实现手动通知的类必须覆盖自动通知ObserversForKey: 的NSObject 实现。可以在同一类中同时使用自动和手动观察者通知。对于执行手动通知的属性,automaticNotifiesObserversForKey: 的子类实现应该返回 NO。子类实现应该为任何无法识别的键调用 super。清单 2 中的示例启用了 openingBalance 属性的手动通知,允许超类确定所有其他键的通知。

于 2013-01-04T14:23:27.880 回答