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底层实现
- 编译器创建被观察对象的类的子类NSKVONotifying_<OBJNmae>
- 子类中重写被观察属性的setter方法,增加调用触发处理代码的方法
- (void)willChangeValueForKey:(NSString *)key;
- (void)didChangeValueForKey:(NSString *)key;
- 利用isa swizze交换isa指针为NSKVONotifying_<OBJName>
- 重写子类的class方法,让其返回值跟原对象一致。
- 重写 dealloc, _isKVOA
参考:一篇讲得比较详细的文章
这篇值得一读:KVO源码浅析