KVO automaticallyNotifiesObserversForKey:
Return YES if the key-value observing machinery should automatically invoke -willChangeValueForKey:/-didChangeValueForKey:, -willChange:valuesAtIndexes:forKey:/-didChange:valuesAtIndexes:forKey:, or -willChangeValueForKey:withSetMutation:usingObjects:/-didChangeValueForKey:withSetMutation:usingObjects: whenever instances of the class receive key-value coding messages for the key, or mutating key-value coding-compliant methods for the key are invoked. Return NO otherwise. Starting in Mac OS 10.5, the default implementation of this method searches the receiving class for a method whose name matches the pattern +automaticallyNotifiesObserversOf[Key], and returns the result of invoking that method if it is found. So, any such method must return BOOL too. If no such method is found YES is returned.
解读:
- 返回 BOOL 类型
- 返回 YES 的情况下,类的实例对象接收到 KVC 类型的实例方法时,如 setValueForKey: 等,或变相的遵守 KVC 的该 key 的访问器方法被调用时,如 setKey: 等,KVO 内部机制会自动调用 -willChangeValueForKey:, -didChangeValueForKey:等,自动发送 Change 通知。
- -willChangeValueForKey:, -didChangeValueForKey: 调用是触发通知的源头,这也就解释了手动发送 Change 通知时,为何需要写这两个方法。
- 若不开启自动改变通知,则应返回 NO。
- 从 Mac OS 10.5 开始,这个方法的默认实现逻辑是:会先查找消息接受方的类是否有 key 匹配的 +automaticallyNotifiesObserversOf[Key] 方法,如:+automaticallyNotifiesObserversOfName,若有,则返回匹配方法的结果,若没有则返回 YES。
当我们对 keyPath 注册观察者时,就会调用该方法。
问:若 automaticallyNotifiesObserversForKey: 和 +automaticallyNotifiesObserversOf[Key] 同时存在时,先调用哪个?
答:+automaticallyNotifiesObserversOf[Key] 的 caller 是 automaticallyNotifiesObserversForKey:,自然先调用automaticallyNotifiesObserversForKey:,+automaticallyNotifiesObserversOf[Key] 是 automaticallyNotifiesObserversForKey:的内部实现逻辑。若子类重写了 automaticallyNotifiesObserversForKey:,则相同的 key,只能调用其中一个方法,且只调用 automaticallyNotifiesObserversForKey:。
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
BOOL automatic;
if ([key isEqualToString:@"name"]) {
automatic = NO;
} else {
automatic = [super automaticallyNotifiesObserversForKey:key];
}
return automatic;
}
+ (BOOL)automaticallyNotifiesObserversOfName {
return NO;
}