NSNotification(通知模式):
gitHub download:cwRichardKim/RKNotificationHub
是界面间通信的一种方式.这种模式的实现,是通过某一个界面去发送通知,其它任意数量的对象只要遵循某一种原则,都可以接收到这个通知消息.即使这些对象之间没有耦合关系.
用得到NSNotification(通知)的地方不是太多(最后会分析原因),比较常用的一种场景是"换皮肤",就是更换UITabBar,UINavigationBar的背景,以达到换肤的效果(下面会代码举例).
我们先来分析一下NSNotification(通知)类.
NSNotification(通知),它封装了要广播的信息.NSNotificationCenter(通知中心),这个类管理注册接收消息对象,发送通知消息等.
一、NSNotification
了解几个相关的类
- 这个类可以理解为一个消息对象,其中有三个成员变量。
//这个成员变量是这个消息对象的唯一标识,用于辨别消息对象。
[@property](http://my.oschina.net/property) (readonly, copy) NSString *name;
//这个成员变量定义一个对象,可以理解为针对某一个对象的消息。
[@property](http://my.oschina.net/property) (readonly, retain) id object;
//这个成员变量是一个字典,可以用其来进行传值。
[@property](http://my.oschina.net/property) (readonly, copy) NSDictionary *userInfo;
- NSNotification的初始化方法:(注意:官方文档有明确的说明,不可以使用init进行初始化)
- (instancetype)initWithName:(NSString *)name object:(id)object userInfo:(NSDictionary *)userInfo;
+ (instancetype)notificationWithName:(NSString *)aName object:(id)anObject;
+ (instancetype)notificationWithName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
二、NSNotificationCenter
这个类是一个通知中心,使用单例设计,每个应用程序都会有一个默认的通知中心。用于调度通知的发送的接受。
- 添加一个观察者,可以为它指定一个方法,名字和对象。接受到通知时,执行方法。
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
- 发送通知消息的方法
- (void)postNotification:(NSNotification *)notification;
- (void)postNotificationName:(NSString *)aName object:(id)anObject;
- (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
- 移除观察者的方法
- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;
几点注意:
1、如果发送的通知指定了object对象,那么观察者接收的通知设置的object对象与其一样,才会接收到通知,但是接收通知如果将这个参数设置为了nil,则会接收一切通知。
2、观察者的SEL函数指针可以有一个参数,参数就是发送的死奥西对象本身,可以通过这个参数取到消息对象的userInfo,实现传值。
三、通知的一个周期大体又分做三个流程.
1、首先,我们在需要接收通知的地方注册观察者,比如:
//获取通知中心单例对象
NSNotificationCenter * center = [NSNotificationCenter defaultCenter];
//添加当前类对象为一个观察者,name和object设置为nil,表示接收一切通知
[center addObserver:self selector:@selector(notice:) name:@"123" object:nil];
2、之后,在我们需要时发送通知消息
//创建一个消息对象
NSNotification * notice = [NSNotification notificationWithName:@"123" object:nil userInfo:@{@"1":@"123"}];
//发送消息
[[NSNotificationCenter defaultCenter]postNotification:notice];
3、我们可以在回调的函数中取到userInfo内容,如下:
-(void)notice:(id)sender{
NSLog(@"%@",sender);
}
四、换肤demo:
1、首先要去触发这个通知事件,例如上面提到的"换皮肤",我们可以在某一个"不相干"的页面创建一个UIButton(代码省略),给这个UIButton添加一个button的点击事件,让这个button去触发通知事件,下面代码实现了发送通知,注意,NSNotificationCenter是单例类
// button的点击事件
// 发送通知
// 注意:postNotificationName:后面的名字(字符串)非常重要,和前面在注册时用到的名字必须一致(下面讲解)
// userInfo携带的参数,类型是字典
- (void)actionButton:(UIButton*)button
{
[[NSNotificationCenterdefault Center]postNotificationName:@"NOTIFICATIONONE"
object:selfuserInfo:@{@"UI":@"Over"}];
}
2、然后我们想在哪个界面去接收到这个通知,就去哪个页面注册通知(多个页面也可以,但保证都要注册),注册也是一行代码,我们这里想改变根视图的背景颜色,所以要在AppDelegate.m**中去注册这个通知:
// 注册一条通知,接受参数
// 通知的名字,最好是全大写,并且必须和前面发送通知时的名字一致
[[NSNotificationCenterdefault Center]addObserver:selfselector:@selector
(notification:)name:@"NOTIFICATIONONE"object:nil];
3、实现方法
下面实现notification:方法,在其中改变根视图的背景
// 实现接收通知的方法
- (void)notification:(NSNotification*)notification
{
// 1.把window的根视图控制器取出来
UIViewController*vc =self.window.rootViewController;
// 2.把已经设置window的根视图控制器重置为空
self.window.rootViewController=nil;
// 3.设置新皮肤
// 取出NavBar 和TabBar
// 通过调用appearance取出要更改的bar
UINavigationBar *navBar = [UINavigationBarappearance];
UITabBar *tabBar = [UITabBarappearance];
// 设置新的背景,如果这里有多条通知同时响应这个方法,可以通过实参notification中的name属性判定
[navBarsetBarTintColor:[UIColo rredColor]];
[tabBarsetBarTintColor:[UIColor redColor]];
// 4.重新赋值window的根视图控制器
self.window.rootViewController= vc;
// 这里还能取到发送通知时传过来的字典
NSDictionary*dic = not.userInfo;
NSLog(@"我收到通知了 %@ 通知的名字 %@ object:%@",dic, not.name,not.object);
}
附加:(mrc下)最后,如果已经注册的对象不需要接受信息时,在通知中心移除,移除的位置在dealloc中()
{
// 销毁这条通知
[[NSNotificationCenterdefault Center]removeObserver:selfname:@"NOTIFICATIONONE"
object:nil];
[super dealloc];
}
文章最后,我们说说NSNotification(通知)的优劣势
1、优势前面已经提到过,最大的优势就是可以一对多,即使对象之间没有耦合关系.
2、那为什么不常用呢,
- 一是因为代码的可读性比较差,不太容易寻找它们之间的联系
- 二是因为NSNotification(通知)这种方式不像代理一样注重返回的情况,通知模式下我只管发出通知,接不接收与我无关,怎样接收也与我无关,这就造成了通知的相对独立性,不能做到太好的前后照应,从整体性来看,还是存在一定的弊端.-