我对使用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,无论是否有任何改变......
有人可以解释我的情况与文档中解释的不同吗?
答案 0 :(得分:6)
来自文档。如果您需要手动,则必须覆盖:
手动更改通知
手动更改通知可以更精细地控制方式和方式 何时向观察员发送通知。这对帮助有用 最小化不必要的触发通知,或者对a进行分组 单个通知的更改次数。
实现手动通知的类必须覆盖NSObject 执行automaticNotifiesObserversForKey:。它是 可以使用自动和手动观察者通知 同一个班级。对于执行手动通知的属性, selfNotifiesObserversForKey的子类实现: 应该返回NO。子类实现应该调用super for 任何无法识别的密钥。清单2中的示例启用了手动 允许超类的opensBalance属性的通知 确定所有其他密钥的通知。