观察者设计模式

KVO也叫“发布--订阅”模式,很像杂志的订阅。

读者把名字和邮寄地址提供给发行商

发行商在发行新一期的的杂志时,就能将杂志送到每一个读者手中


原理:

订阅者注册成为发布者的某一属性的观察者

当发布者的这一属性发生变化时,所有的观察者都会得知该属性的变化

KVC(键值编码)是实现KVO的基础

与代理的功能类似,用来实现:对象间传递事件、数值,但不能为自身属性赋值


观察者设计的使用步骤

1)发布者添加属性

如一个Person类,添加属性age

@interfaceAMPerson:NSObject@property(nonatomic,strong)NSNumber*age;@end

2)注册成为订阅者

发布者调用addObserver:forKeyPath:options:context:方法,注册其指定属性的订阅者

-(void)addObserver:(NSObject*)observerforKeyPath:(NSString*)keyPathoptions:(NSKeyValueObservingOptions)optionscontext:(void*)context

如控制器创建一个Person对象,并成为其订阅者

self.person=[[AMPersonalloc]init];self.person.age=@10;[self.personaddObserver:selfforKeyPath:@"age"options:NSKeyValueObservingOptionNewcontext:nil];

3)订阅者实现observeValueForKeyPath:ofObject:change:context:方法

-(void)observeValueForKeyPath:(NSString*)keyPathofObject:(id)objectchange:(NSDictionary<NSString*,id>*)changecontext:(void*)context

如:

-(void)observeValueForKeyPath:(NSString*)keyPathofObject:(id)objectchange:(NSDictionary<NSString*,id>*)changecontext:(void*)context{if([keyPathisEqualToString:@"age"]){NSLog(@"%@",change);}}

4)发布者的属性发生变化时订阅者会响应

响应方法即发布者的observeValueForKeyPath:ofObject:change:context:方法

注意:必须使用KVC的赋值方式订阅者才会响应

如:

NSIntegerage=self.person.age.integerValue+1;[self.personsetValue:@(age)forKey:@"age"];

5)订阅者销毁前将注册信息删除

发布者使用removeObserver:forKeyPath:方法删除指定的订阅者

-(void)removeObserver:(NSObject*)anObserverforKeyPath:(NSString*)keyPath

如:

-(void)dealloc{[self.personremoveObserver:selfforKeyPath:@"age"];}



通知机制

通知机制是基于观察者设计模式实现一种对象间的通信技术。

虽然Objective-C的对象支持直接使用观察者设计模式开发,但通知机制的使用过程更加简单

通知中心是一种多对多的通信方式,而观察者仅仅是一对多的通信方式



通知中心:

每个应用程序都有一个实现通知机制的实例,称作通知中心(NSNotificationCenter)

获得其单例对象:

+(NSNotificationCenter*)defaultCenter

通知中心还包含添加、删除通知关系的方法


通知的发布者:

任何对象都可以向通知中心发布消息


通知的接受者:(响应者)

任何对象都可以在通知中心注册所关心的消息,并在关系消息被发布时收到


通知对象(NSNotification)主要包含以下三个属性:

@property(readonly,copy)NSString*name//通知名@property(readonly,retain)idobject//通知的发布者@property(readonly,copy)NSDictionary*userInfo//通知中可以携带的数据


通知的使用过程

1)起一个通知的名字

一般在发布者源文件中定义并在头文件中声明

//AMAppView.hexternNSString*constAMAppViewNameBtnClickedNotification;//AMAppView.mNSString*constAMAppViewNameBtnClickedNotification=@"AMAppViewNameBtnClickedNotification";

2)通知发布者通过通知中心发布通知

通知中心使用postNotification方法发布通知

-(void)postNotification:(NSNotification*)notification-(void)postNotificationName:(NSString*)notificationNameobject:(id)notificationSender-(void)postNotificationName:(NSString*)notificationNameobject:(id)notificationSenderuserInfo:(NSDictionary*)userInfo

如:

[[NSNotificationCenterdefaultCenter]postNotificationName:AMAppViewNameBtnClickedNotificationobject:selfuserInfo:@{@"appModel":self.appModel}];

3)通知接收者通过通知中心注册想要接收的通知

使用通知中心的addObserver方法

-(void)addObserver:(id)notificationObserverselector:(SEL)notificationSelectorname:(NSString*)notificationNameobject:(id)notificationSender-(id<NSObject>)addObserverForName:(NSString*)nameobject:(id)objqueue:(NSOperationQueue*)queueusingBlock:(void(^)(NSNotification*note))block

如:

[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(appViewNameBtnClicked:)name:AMAppViewNameBtnClickedNotificationobject:v];

4)通知接收者实现通知的响应方法或block

-(void)appViewNameBtnClicked:(NSNotification*)notification{NSLog(@"%@",notification.name);NSLog(@"%@",notification.object);NSLog(@"%@",notification.userInfo);}

5)通知接收者在被销毁或者不再想接收通知时,从通知中心移除

使用通知中心的removeObserver方法

-(void)removeObserver:(id)notificationObserver-(void)removeObserver:(id)notificationObservername:(NSString*)notificationNameobject:(id)notificationSender

一般放在接受者的dealloc方法中调用,如:

-(void)dealloc{[[NSNotificationCenterdefaultCenter]removeObserver:self];}


使用场景的区别:

代理设计模式:一对一的关系 对象间关系相对比较紧密

观察者设计模式:一对多的关系

通知机制:多对多的关系