【前言介绍】
iOS的一种设计模式,观察者Observer模式(也叫发布/订阅,即Publich/Subscribe模式)。观察者模式,包含了通知机制(notification)和KVO(Key-value-observing)机制。在这本文中,我们将介绍在日常项目当中经常使用到的通知机制这一种设计模式。
通知机制
委托机制是代理“一对一”的对象之间的通信,而通知机制是广播“一对多”的对象之间的通信;
一、是什么?【生活问题例子】
“短信天气预报”
当A类发送一条信息给通知中心时,注册为用户(观察者)的B类群就会收到相应的通知,并作出反应。
二、有什么用?【代码中的应用】
在不同类之间如何传递数据?
有几种方法:属性传递、代理协议,另外就是通知。
通知:在A类中创建的方法,B类中执行,且可以使用该通知携带数据传递给对方;
三、有什么不同?【与其他“通知”的不同?】
经常提到的通知,有“广播通知”、“本地通知”、“推送通知”
本文所介绍的就是广播通知,是实现观察者模式的一种机制,可以在一个应用中的多个对象之间进行通信传递数据。
而本地通知和推送通知主要是给用户发送“通知提示”,例如警告提示、声音、震动以及如图标上的红色数字提示。
第一种由“本地发送通知”给用户,第二种由第三方应用发送给苹果官方的远程服务器,然后再由服务器“推送通知”给用户。
四、产品经理:老规矩,代码拿来~【具体实现】
过程:
- 在通知机制中,需要(或者说感兴趣)接收某个通知的信息的所有对象都可以成为接收者,首先注册成为观察者。
- 进行注册后,通知中心就会把发布者发送的通知信息,广播给注册过该通知的观察者。且观察者只能接收到通知中心的信息,不能知道通知是谁投送的。
- 最后,接受者不想再对关注该通知的信息时,可以给通知中心发生解除注册的信息,之后都不再接收到通知了。
1.获取通知中心(NSNotificationCenter)对象:(就像获取移动营运商短信中心的权限,作为媒介)
发布、注册、解除通知都需要使用通知中心,负责协助不同对象、不同类之间的消息通信。
1 |
[NSNotificationCenter defaultCenter]; //需要注意的是,通知中心也是一个单例 |
2.发布(A类)和接收(B类)
a.做为发布者的A类发送通知:
可以使用一下三个方法:
1 2 3 4 5 |
- (void)postNotification:(NSNotification *)notification; - (void)postNotificationName:(NSString *)aName object:(id)anObject; - (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo; |
- postNotificationName:指定消息名称;
- object:指定发消息者;
- userInfo:通知中用于传递参数的载体,传递的方法是把参数放在NSDictionary类型的userInfo中。例如:NSDictionary *dict = [notification userInfo];
一般使用第三个方法,如果参数不需要的,可以设置为nil.
b.注册通知,加入观察者:
做为观察者B类注册通知,进行监听:
1 |
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSString *)aName object:(nullable id)anObject; |
1 |
//@selector中为回调方法,在本类中对通知进行相应的处理,name为通知名称、object为对象; |
剖析:
- object == nil,那么客户对象(self)将收到任何对象发出NSWindowDidBecomeMainNotification的通知消息;
- name == nil,那么观察者将接收到object对象的所有消息,但是确定不了接收这些消息的顺序。
- object == nil,name == nil,那么该观察者将收到所有对象的所有消息。
对于一个任意的观察者observer,如果不能保证其对应的selector有本类自定义的方法(例如:MyMethod),可采用[observer respondsToSelector:@selector(MyMethod:)]] 进行检查。
所以完整的添加观察者过程为:
1 2 3 |
if([observer respondsToSelector:@selector(MyMethod:)]) { [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(MyMethod:) name:NSWindowDidBecomeMainNotification object:nil]; } |
当然在苹果API中也有另外一个注册观察者的方法:
1 |
- (id )addObserverForName:(nullable NSString *)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block |
此方法是支持在该方法中进行block回调的,而queue参数就是表示此模块在queue队列中进行。
但是这方法一般不采用,所以建议使用第一种方法进行观察者的创建。
c.移除通知
由于通知中心不会retain观察者对象,因此注册过的对象必须在释放之前注销掉,如果不这样的话,当该通知再次出现时,通知中心会向已释放的观察者对象发送消息,从而导致应用崩溃。
在ARC下,系统会自动回收无用的通知对象内存,但是由于系统回收机制ARC有一定的延迟性,所以即使不会出错,也建议养成习惯,对通知进行手动释放无用的通知。
移除有2种方法:
1 2 |
//释放所有通知- (void)removeObserver:(id)observer;//释放名称为aName的通知 - (void)removeObserver:(id)observer name:(nullable NSString *)aName object:(nullable id)anObject; |
一般在视图控制器中,可以在“didReceiveMemoryWarning:”中发送解除消息:
1 2 3 4 5 6 |
-(void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; 叫发布/订阅,即Publich/Subscribe模式)。观察者模式,包含了通知机制(notification)和KVO(Key-value-observing)机制。在这本文中,我们将介绍在日常项目当中经常使用到的通知机制这一种设计模式。
通知机制 委托机制是代理“一对一”的对象之间的通信,而通知机制是广播“一对多”的对象之间的通信; 一、是什么?【生活问题例子】 “短信天气预报” 当A类发送一条信息给通知中心时,注册为用户(观察者)的B类群就会收到相应的通知,并作出反应。 二、有什么用?【代码中的应用】 在不同类之间如何传递数据? 有几种方法:属性传递、代理协议,另外就是通知。 通知:在A类中创建的方法,B类中执行,且可以使用该通知携带数据传递给对方; 三、有什么不同?【与其他“通知”的不同?】 经常提到的通知,有“广播通知”、“本地通知”、“推送通知” 本文所介绍的就是广播通知,是实现观察者模式的一种机制,可以在一个应用中的多个对象之间进行通信传递数据。 而本地通知和推送通知主要是给用户发送“通知提示”,例如警告提示、声音、震动以及如图标上的红色数字提示。 第一种由“本地发送通知”给用户,第二种由第三方应用发送给苹果官方的远程服务器,然后再由服务器“推送通知”给用户。 四、产品经理:老规矩,代码拿来~【具体实现】 过程:
1.获取通知中心(NSNotificationCenter)对象:(就像获取移动营运商短信中心的权限,作为媒介) 发布、注册、解除通知都需要使用通知中心,负责协助不同对象、不同类之间的消息通信。
2.发布(A类)和接收(B类) a.做为发布者的A类发送通知: 可以使用一下三个方法:
一般使用第三个方法,如果参数不需要的,可以设置为nil. b.注册通知,加入观察者: 做为观察者B类注册通知,进行监听:
剖析:
对于一个任意的观察者observer,如果不能保证其对应的selector有本类自定义的方法(例如:MyMethod),可采用[observer respondsToSelector:@selector(MyMethod:)]] 进行检查。 所以完整的添加观察者过程为:
当然在苹果API中也有另外一个注册观察者的方法:
此方法是支持在该方法中进行block回调的,而queue参数就是表示此模块在queue队列中进行。 但是这方法一般不采用,所以建议使用第一种方法进行观察者的创建。 c.移除通知 由于通知中心不会retain观察者对象,因此注册过的对象必须在释放之前注销掉,如果不这样的话,当该通知再次出现时,通知中心会向已释放的观察者对象发送消息,从而导致应用崩溃。 在ARC下,系统会自动回收无用的通知对象内存,但是由于系统回收机制ARC有一定的延迟性,所以即使不会出错,也建议养成习惯,对通知进行手动释放无用的通知。 移除有2种方法:
一般在视图控制器中,可以在“didReceiveMemoryWarning:”中发送解除消息:
|