KVO
KVO:键值观察。观察者模式的衍生,对目标对象的属性添加观察,当该属性发生变化时,通过触发观察者对象实现KVO接口方法,来自动的通知观察者。
KVO底层实现:某个类的对象第一次被观察时,系统会在运行时动态创建该类的一个派生类,并在派生类中重写setter方法,在setter方法实现真正的通知机制(如:Person-》NSKVONotifying_Person),外部调用的类其实调用的是这个派生类。系统对象的isa指针指向新的派生类,对setter的调用就激活键值通知机制。
KVO与Notification之间的区别:
notification是需要一个发送notification的对象,一般是notificationCenter,来通知观察者
KVO是直接通知到观察对象,并且逻辑非常清晰,实现步骤简单
KVO 例子:
添加观察者: [a addObserver:b forKeyPath:@"name" options:kNilOptions context:nil];
在观察者中实现监听方法,observeValueForKeyPath: ofObject: change: context:
移除观察者: [a removeObserver:b forKeyPath:@"name"];
数据修改: a.name = @"zzz"
KVC
KVC:键值编码。开发者通过key名直接访问对象的属性,或者给对象的属性赋值,而不需要调用明确的存取方法。这样就可以在运行时动态访问和修改对象的属性,而不是在编译时确定。
KVC底层实现:
(1).KVC取值:
1.首先查找getter方法,找到的话直接调用。如果是BOOL或者Int等值,将其包装成一个NSNumber对象。
2.如果对象的getter没有找到,KVC则会查找countOf,objectInAtIndex或AtIndexes格式的方法。如果找到countOf和(objectInAtIndex或AtIndexes中的一个),那么就会返回一个可以响应NSArray所有方法的代理集合(NSKeyValueArray,是BSArray的子类)。
3.如果上面的方法都没有找到,那么会同时查找countOf,enumeratorOf,memberOf格式的方法。如果都找到,返回一个可以响应NSSet所有的方法的代理集合。
4.如果还没有找到,再检查类方法+(BOOL)accessInstanceVariablesDirectly,如果返回YES,会按照_,_is,is的顺序搜索成员变量。不推荐这样做。如果重写+(BOOL)accessInstanceVariablesDirectly返回NO的话,那么会直接调用valueForUndefinedKey:方法,默认是抛出异常。
(2).KVC设值:
1.程序优先调用set属性值方法,代码通过setter方法完成设置
2.如果没有找到setName方法,KVC机制会检查+(BOOL)accessInstanceVariablesDirectly方法
3.如果该类即没有set方法,也没有_成员变量,KVC机制会搜索_is的成员变量
4.和上面一样,没有set方法,也没有_和_is成员变量,KVC机制再会继续搜索和is的成员变量
5.如果上面列出的方法或者变量都不存在,系统将会执行该对象的setValue:forUndefinedKey:方法,默认跑出异常
(3).KVC 例子
1.对私有变量进行赋值:[p setValue:@"张三" forKey:@"name"] [p setValue:@200 forKeyPath:@"dog.weight"]
2.字典转模型 [self setValuesForKeysWithDictionary:dict]