• ios NSNotification(通知模式)


    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(通知)这种方式不像代理一样注重返回的情况,通知模式下我只管发出通知,接不接收与我无关,怎样接收也与我无关,这就造成了通知的相对独立性,不能做到太好的前后照应,从整体性来看,还是存在一定的弊端.-
    成功的三大原则: 1、坚持 2、不要脸 3、坚持不要脸
  • 相关阅读:
    技术选型总结
    这些年来收集的好用的好玩的软件,强烈推荐给大家
    如何解决markdown中图片上传的问题
    01.如何把.py文件打包成为exe,重点讲解pyinstaller的用法
    Asp.net中汉字转换成为拼音
    程序员常用网址收集
    通过IP来判断所在城市
    以太坊
    分布式系统领域经典论文翻译集
    T50
  • 原文地址:https://www.cnblogs.com/xulinmei/p/7420098.html
Copyright © 2020-2023  润新知