我应该在自定义setter中使用will / didSetValueForKey吗?

时间:2013-01-04 13:44:23

标签: objective-c ios ios6 key-value-observing

  

可能重复:
  Receiving 2 KVO notifications for a single KVC change

我对使用willChangeValueForKey: and didChangeValueForKey:的位置感到困惑。

我有一个具有属性的对象,该属性需要自定义setter方法。根据{{​​3}},我使用will/didChangeValueForKey:

  

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

     

清单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:的直接结果(即我的自定义setter没有出现在堆栈中)。 / p>

为了进一步增加混淆,如果我在_Property中的其他位置更改cObject,我的观察者将得到通知(除非我使用{{1}当然!)。

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

有人可以解释我的情况与文档中解释的不同吗?

1 个答案:

答案 0 :(得分:6)

来自文档。如果您需要手动,则必须覆盖:

  

手动更改通知

     

手动更改通知可以更精细地控制方式和方式   何时向观察员发送通知。这对帮助有用   最小化不必要的触发通知,或者对a进行分组   单个通知的更改次数。

     

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