15.键值编码KVC、键值观察KVO

2021-12-27  本文已影响0人  LucXion

键值编码是Cocoa的标准组件,允许开发者通过名字(键)访问属性,

valueForKeyPath 与 valueForKey

NSArray *arr = @[@{@"city":@"beijing",@"person":@"Zh"},@{@"city":@"chengdu",@"student":@"Li"}];
    id result = [arr valueForKeyPath:@"city"];// 可以包含嵌套关系,用句点分开
    id result2 = [arr valueForKey:@"city"];
    // 打印结果都是  beijing,chengdu
    NSLog(@"result = %@,result2 = %@",[result description],[result2 description]);

// 假如一个对象没有numbers属性,那么KVC系统会按顺序搜索如下方法是否实现,用第一个找到的方法来返回值
// 无论是否声明在.h文件中,函数的实现返回值为Void类型,返回值 = nil
getNumbers、numbers、isNumbers;
// 命名为_numbers、_isNumbers、numbers、isNumbers的实例变量,KVC会直接访问ivar,一般最好避免这种行为,直接访问实例变量破坏了封装原则,使代码更脆弱,通过覆盖+ (BOOL)accessInstanceVariablesDirectly方法并返回NO可以避免这种行为。
  

KVO

只要通过存取的方式修改实例变量,那么所有的观察机制都会自动生效,不需要付出任何成本。

KVO和容器类

如果要观察容器内对象的改变,一般可以先观察容器,在添加对象后观察对象,在删除对象后停止观察。

KVO如何实现

键值观察通知依赖于NSObject的两个方法,willChangeValueForKey: 和didChangeValueForKey:,当发生改变后observeValueForKeyPath:ofObject:change: context:会被调用。

这是通过方法混写来实现的:第一次对一个对象调用addObserver: forKeyPath: options: context:,框架会创建这个类的KVO子类,并将被观察对象转化为新子类的对象,这种继承和方法是在运行时实现的,前提是必须使用KVC命名约定。

KVO混写不容易发现,它会复写class方法,返回原来的类,但有时我们能看到NSKVONotifying_MyClass而不是MyClass的调用。

在存在复杂的相互依赖关系或复杂的类继承层次的地方避免使用KVO,用委托或NSNotification的方式比较合适。

上一篇下一篇

猜你喜欢

热点阅读