NSNotificationCenter/NSNotificat

作者: 当红辣椒炒肉 | 来源:发表于2016-12-04 23:06 被阅读858次
    图片来源NSHipster

    为什么有NSNotification

    1. 可以实现跨层的传递,例如A页面导航到B页面,B页面再导航到C页面,这时候如果我们通过委托回调的模式让A知道C的一些修改,那么实现起来就会很麻烦。
    2. 可以实现一对多,NSNotification的实现是一种观察者模式,因此可以对通知实现广播。

    使用通知的要点

    1. ** 注册多少次,他的执行代码就会执行多少次 **
    //1、注册多个通知
    for (int i =0; i<3; i++) {
            [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(notifycationMehod:) name:@"testNotifycation" object:nil];
        }
    //2、传递通知
     [[NSNotificationCenter defaultCenter]postNotificationName:@"testNotifycation" object:nil];
    

    输出结果

    2016-12-01 17:06:23.868 NotifycationDemo[28703:10079806] receive notifycation object (null)
    2016-12-01 17:06:23.868 NotifycationDemo[28703:10079806] receive notifycation object (null)
    2016-12-01 17:06:23.869 NotifycationDemo[28703:10079806] receive notifycation object (null)
    
    1. 虽然注册多次通知,但是移除一次通知,同一个对象通知就会全部移除**
    //添加多个通知
        for (int i =0; i<3; i++) {
            [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(notifycationMehod:) name:@"testNotifycation" object:nil];
        }
    //移除通知
        [[NSNotificationCenter defaultCenter]removeObserver:self name:@"testNotifycation" object:nil];
        //发送通知
        [[NSNotificationCenter defaultCenter]postNotificationName:@"testNotifycation" object:nil];
    

    这里不会有任何输出

    1. add和Remove相关方法成对出现
      我们平时在使用通知的时候可能会在viewWillAppear方法里面add观察者,viewWillDisappear里面remove,但是我们如果忘记remove,那么如果我们导航到当前页面再导航到另外一个页面,然后再退回当前页面,这时候我们会得到2个输出结果。
    - (void)viewWillAppear:(BOOL)animated{
        [super viewWillAppear:animated];
        //注册通知
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(notifycationMehod:) name:@"testNotifycation" object:nil];
    }
    
    - (void)viewWillDisappear:(BOOL)animated{
        [super viewWillDisappear:animated];
        //没有remove通知
    }
    

    输出结果

    2016-12-01 17:24:13.722 NotifycationDemo[28820:10087367] receive notifycation object (null)
    2016-12-01 17:24:13.723 NotifycationDemo[28820:10087367] receive notifycation object (null)
    

    4 . 移除一个name没有add的通知,不会崩溃

    [[NSNotificationCenter defaultCenter]removeObserver:self name:@"unknownName" object:nil];
    

    5 . 一个对象添加了观察者,但是没有移除,程序不会崩溃,这是为啥

    @implementation NotifyTestClass
    
    - (void)registerMyNotifycation{
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(notifycationMehod) name:@"testNotifycation" object:nil];
    }
    
    - (void)notifycationMehod{
        NSLog(@"NotifyTestClass receive notify");
    }
    
    - (void)dealloc{
        NSLog(@"NotifyTestClass dealloc");
    }
    @end
    
    //局部变量 立刻释放
     NotifyTestClass *nt = [[NotifyTestClass alloc]init];
     [nt registerMyNotifycation];
    //发送通知
    [[NSNotificationCenter defaultCenter]postNotificationName:@"testNotifycation" object:nil];
    

    输出结果

    2016-12-01 19:29:15.039 NotifycationDemo[29035:10119206] NotifyTestClass dealloc
    

    为了验证这个问题我按这篇文章中提到的方法对NSNotificationCenter新建了一个category,然后重写了remove方法;

    //新建一个类别
    @implementation NSNotificationCenter(NSNotificationCenterRemove)
    
    - (void)removeObserver:(id)observer{
        NSLog(@"removeObserver = %@",observer);
    }
    - (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject{
        NSLog(@"observer %@ name %@",observer,aName);
    }
    @end
    

    然后我在输出结果里面还是没有看到在变量被dealloc之后有调用remove方法。因为按照这篇文章在最后说到通知中心对观察者是unsafe_unretained引用,不是weak引用(weak和unsafe_unretained的区别,可以看我上一篇文章里面有提到),所以这个时候应该会崩溃的,因为相当于我对一个不存在的对象(野指针)发送了消息。这个问题困扰了我两天没搞明白,最后在一个群里问大家才发现问题的所在,苹果官网文档有说明,iOS 9.0之后NSNotificationCenter不会对一个dealloc的观察者发送消息所以这样就不会崩溃了。果真我换了一个8.1的手机测试,程序崩溃了,原来是做了优化。

    野指针异常 苹果官网提示

    6 . ViewController对象在销毁的时候,系统会对他监听的通知进行清除

    @implementation TwoViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(notifycationMehod) name:@"testNotifycation" object:nil];
        // Do any additional setup after loading the view from its nib.
    }
    - (void)notifycationMehod{
        NSLog(@"TwoViewController receive notify");
    }
    - (void)dealloc{
        NSLog(@"TwoViewController dealloc");
    }
    @end
    

    输出结果

    2016-12-02 16:36:42.175 NotifycationDemo[31359:10305477] TwoViewController dealloc
    2016-12-02 16:36:42.176 NotifycationDemo[31359:10305477] removeObserver = <TwoViewController: 0x7fa42381d720>
    

    7 . 处理方法是和post通知方法在同一线程同步执行的
    因此我们如果要接受一些通知更新UI的时候,我们需要回到主线程来处理。

     dispatch_async(dispatch_get_main_queue(), ^{
            //do your UI
        });
    

    相关文章

      网友评论

      • Vine_Finer:说这么多,还是不知道怎么用

      本文标题:NSNotificationCenter/NSNotificat

      本文链接:https://www.haomeiwen.com/subject/hwoxmttx.html