观察者设计模式
KVO也叫 “发布--订阅”模式,很像杂志的订阅。
读者把名字和邮寄地址提供给发行商
发行商在发行新一期的的杂志时,就能将杂志送到每一个读者手中
原理:
订阅者注册成为发布者的某一属性的观察者
当发布者的这一属性发生变化时,所有的观察者都会得知该属性的变化
KVC(键值编码)是实现KVO的基础
与代理的功能类似,用来实现:对象间传递事件、数值,但不能为自身属性赋值
观察者设计的使用步骤
1)发布者添加属性
如一个Person类,添加属性age
@interface AMPerson : NSObject @property (nonatomic, strong) NSNumber* age; @end
2)注册成为订阅者
发布者调用addObserver:forKeyPath:options:context:方法,注册其指定属性的订阅者
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
如控制器创建一个Person对象,并成为其订阅者
self.person = [[AMPerson alloc] init]; self.person.age = @10; [self.person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];
3)订阅者实现observeValueForKeyPath:ofObject:change:context:方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
如:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { if ( [keyPath isEqualToString:@"age"] ) { NSLog(@"%@", change); } }
4)发布者的属性发生变化时订阅者会响应
响应方法即发布者的observeValueForKeyPath:ofObject:change:context:方法
注意:必须使用KVC的赋值方式订阅者才会响应
如:
NSInteger age = self.person.age.integerValue+1; [self.person setValue:@(age) forKey:@"age"];
5)订阅者销毁前将注册信息删除
发布者使用removeObserver:forKeyPath:方法删除指定的订阅者
- (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
如:
- (void)dealloc { [self.person removeObserver:self forKeyPath:@"age"]; }
通知机制
通知机制是基于观察者设计模式实现一种对象间的通信技术。
虽然Objective-C的对象支持直接使用观察者设计模式开发,但通知机制的使用过程更加简单
通知中心是一种多对多的通信方式,而观察者仅仅是一对多的通信方式
通知中心:
每个应用程序都有一个实现通知机制的实例,称作通知中心(NSNotificationCenter)
获得其单例对象:
+ (NSNotificationCenter *)defaultCenter
通知中心还包含添加、删除通知关系的方法
通知的发布者:
任何对象都可以向通知中心发布消息
通知的接受者:(响应者)
任何对象都可以在通知中心注册所关心的消息,并在关系消息被发布时收到
通知对象(NSNotification)主要包含以下三个属性:
@property(readonly, copy) NSString *name //通知名 @property(readonly, retain) id object //通知的发布者 @property(readonly, copy) NSDictionary *userInfo //通知中可以携带的数据
通知的使用过程
1)起一个通知的名字
一般在发布者源文件中定义并在头文件中声明
//AMAppView.h extern NSString * const AMAppViewNameBtnClickedNotification; //AMAppView.m NSString * const AMAppViewNameBtnClickedNotification = @"AMAppViewNameBtnClickedNotification";
2)通知发布者通过通知中心发布通知
通知中心使用postNotification方法发布通知
- (void)postNotification:(NSNotification *)notification - (void)postNotificationName:(NSString *)notificationName object:(id)notificationSender - (void)postNotificationName:(NSString *)notificationName object:(id)notificationSender userInfo:(NSDictionary *)userInfo
如:
[[NSNotificationCenter defaultCenter] postNotificationName:AMAppViewNameBtnClickedNotification object:self userInfo:@{@"appModel":self.appModel}];
3)通知接收者通过通知中心注册想要接收的通知
使用通知中心的addObserver方法
- (void)addObserver:(id)notificationObserver selector:(SEL)notificationSelectorname:(NSString *)notificationName object:(id)notificationSender - (id<NSObject>)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block
如:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appViewNameBtnClicked:) name:AMAppViewNameBtnClickedNotification object: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)notificationObserver name:(NSString *)notificationNameobject:(id)notificationSender
一般放在接受者的dealloc方法中调用,如:
- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
使用场景的区别:
代理设计模式:一对一的关系 对象间关系相对比较紧密
观察者设计模式:一对多的关系
通知机制:多对多的关系
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。