KVC&KVO

2018-05-18  本文已影响0人  GTMYang

KVC

Key value coding 键值对编程
OC中KVC相关方法都放在NSKeyValueCoding类别下
所有继承NSObject的类都能使用KVC的方法

几个关键方法

 //直接通过Key来取值
- (nullable id)valueForKey:(NSString *)key;                         
//通过Key来设值
- (void)setValue:(nullable id)value forKey:(NSString *)key;          
//通过KeyPath来取值
- (nullable id)valueForKeyPath:(NSString *)keyPath;                  
//通过KeyPath来设值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;  

//默认返回YES,表示如果没有找到Set<Key>方法的话,会按照_key,_iskey,key,iskey的顺序搜索成员,设置成NO就不这样搜索
+ (BOOL)accessInstanceVariablesDirectly;
// 如果Key不存在,且没有KVC无法搜索到任何和Key有关的字段或者属性,则会调用这个方法,默认是抛出异常。
- (nullable id)valueForUndefinedKey:(NSString *)key;
// 
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
// 如果你在SetValue方法时面给Value传nil,则会调用这个方法
- (void)setNilValueForKey:(NSString *)key;

集合运算符

@avg, @count , @max , @min ,@sum

集合对象运算符

@distinctUnionOfObjects // 返回数组(去掉重复)
@unionOfObjects // 返回数组

使用场景

动态地取值和设值
用KVC来访问和修改私有变量
Model和字典转换
修改一些控件的内部属性
操作集合
用KVC实现高阶消息传递(当对容器类使用KVC时,valueForKey:将会被传递给容器中的每一个对象)

KVO

KVO 即 Key-Value Observing,是一种观察者模式的衍生。
KVO相关方法定义在NSKeyValueObserving类别下
所有继承了NSObject的类型,都能使用KVO

注册与解除注册

- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

/*
options
NSKeyValueObservingOptionNew:change字典包括改变后的值
NSKeyValueObservingOptionOld:  change字典包括改变前的值
NSKeyValueObservingOptionInitial:  注册后立即触发一次KVO通知
NSKeyValueObservingOptionPrior:  值改变前是否也要通知(这个key决定了是否在改变前改变后都通知
*/

处理变更通知

// 重写Observer对象的该方法
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context

手动KVO(禁用KVO)

// 该方法返回NO就禁用
+ (BOOL) automaticallyNotifiesObserversForKey:(NSString *)key

键值观察依赖键

// 重写
+ (NSSet<NSString *> *)keyPathsForValuesAffecting<#DependentKey#>
// 或者重写
+ (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key

KVO底层实现

  1. 编译器创建被观察对象的类的子类NSKVONotifying_<OBJNmae>
  2. 子类中重写被观察属性的setter方法,增加调用触发处理代码的方法
- (void)willChangeValueForKey:(NSString *)key;
- (void)didChangeValueForKey:(NSString *)key;
  1. 利用isa swizze交换isa指针为NSKVONotifying_<OBJName>
  2. 重写子类的class方法,让其返回值跟原对象一致。
  3. 重写 dealloc, _isKVOA

参考:一篇讲得比较详细的文章

这篇值得一读:KVO源码浅析

上一篇下一篇

猜你喜欢

热点阅读