一 KVO
a) 介绍:Objective-C 中的键(key)-值(value)观察(KVO)来源于设计模式中的观察者模式,其基本思想就是:一个目标对象管理所有依赖于它的观察者对象,并在它自身的状态改变时主动通知观察者对象。这个主动通知通常是通过调用各观察者对象所提供的接口方法来实现的。观察者模式较完美地将目标对象与观察者对象解耦。在Objective-C 中有两种使用键值观察的方式:手动或自动,此外还支持注册依赖键(即一个键依赖于其他键,其他键的变化也会作用到该键)。KVO是基于KVC实现的
b) 实现机制:
i. 当某个类的对象第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter 方法。
ii. 派生类在被重写的setter 方法实现真正的通知机制,就如前面手动实现键值观察那样。这么做是基于设置属性会调用setter 方法,而通过重写就获得了KVO 需要的通知机制。当然前提是要通过遵循KVO 的属性设置方式来变更属性值,如果仅是直接修改属性对应的成员变量,是无法实现KVO 的。
iii. 同时派生类还重写了class 方法以“欺骗”外部调用者它就是起初的那个类。然后系统将这个对象的isa 指针指向这个新诞生的派生类,因此这个对象就成为该派生类的对象了,因而在该对象上对setter 的调用就会调用重写的setter,从而激活键值通知机制。此外,派生类还重写了dealloc 方法来释放资源。
c) 运用KVO
i. 注册需要观察的对象的属性addObserver:forKeyPath:options:context:
ii. 实现observeValueForKeyPath:ofObject:change:context:方法,这个方法当观察的属性变化时会自动调用
iii. 在dealloc中移除KVO监听:removeObserver:forKeyPath:context:
二 KVC
a) 介绍:kvc,键值编码,是一个非正式的协议,观察者模式的一种实现,它提供一种机制来间接访问对象的属性。直接访问对象是通过调用访问器的方法实现,而kvc不需要调用访问器的设置和获取方法,可以直接访问对象的属性,从而简化我们的代码,也可以用来修改系统控件内部属性。最常用的场景就是字典转模型
b) 用法:
i. kvc通过键值对的方式对属性设置:- (void)setValue:(id)value forKey:(NSString *)key;
ii. kvc通过键值对的方式获取对象属性,相当于getter方法:- (id)valueForKey:(NSString *)key;
iii. key找不到时,异常处理:- (void)setValue:(id)value forUndefinedKey:(NSString *)key;
iv. 字典转模型:setValuesForKeysWithDictionary
c) 赋值原理:
i. 去模型中查找有没有setter方法,就直接调用这个setter方法,给模型这个属性赋值
ii. 如果找不到set方法,接着就会去寻找有没有这个属性,如果有,就直接访问属性赋值
iii. 如果找不到属性,接着又会去寻找成员变量,直接给成员变量赋值,再找不到就报异常
三 通知
a) 介绍:通知中心(NSNotificationCenter), 是IOS程序内部的一种消息广播机制, 通过它可以完成不同对象之间的通信。如果我们想把消息从A传递到B, 那么通知中心的两端就是发送者A和接收者(也就是观察者)B, 两者通过通知中心就可以完成通信。通知中心与代理模式类似, 但是两者不同的是, 代理模式的每个对象只能添加一个代理, 而通过NSNotificationCenter可以实现一对多的通信, 通知的发布者可以添加多个观察者。
b) 通知(NSNotification)的三个属性:name、object、userInfo
c) 通知中心对于通知的操作有3步:
i. 通知的发布:- (void)postNotification:(NSNotification *)notification;由A把数据传出去,发送通知
ii. 通知的监听:-(void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString*)aNameobject:(id)anObject; 注册B的接收到消息方法
iii. 通知的移除:- (void)removeObserver:(id)observer;在接收消息方法的对象中的dealloc中记得移除通知,否则会崩溃
四 KVO、通知、delegate的区别
a) 代理需要定义代码很多,定义协议、实现协议方法等。通知不需要编写多少代码,实现简单。
b) 代理是1对1传值,通知是1对多传值
c) 代理效率快,通知效率低
d) 代理控制流程可跟踪,并且可识别,通知的工作以及流程难以跟踪查看流程
e) 代理能够接收到协议方法的返回值,通知发出后,观察者方法不能返回数据到发送者。
f) KVO的语法比较通知更简洁
g) KVO监听某个类,通用一个接收方法,使用key做接收到的属性判断,而通知可以实现多个接收通知的方法