iOS通知学习笔记(NSNotification)

跨界面传值有很多种方法,属性传值、方法传值、NSUserDefaults、NSNotification、代理、Block、单例等。

iOS通知Demo链接

发送通知

发送通知通过 -postNotificationName:object: 方法或 - postNotificationName:object:userInfo: 方法进行。

    // 发出通知
    // Name:通知名称
    // object:谁发出的通知
    // userInfo:要传的参数,是个字典
    [[NSNotificationCenter defaultCenter] postNotificationName:@"note" object:nil];

接收通知

接收通知有两种方式,一种是通过方法 - addObserver:selector:name:object:来接收,另一种是通过 -addObserverForName:object:queue:usingBlock: 方法来实现


  • 通过- addObserver:selector:name:object:方法接收通知

需要注意的是,通知的顺序是:先接收通知,再发送通知。很多时候,明明我发送通知和接收通知的方法都写了,为什么接收不到通知啊?原因很有可能就是发送通知方法与接受通知方法的执行顺序反了。

    // 监听通知:这个一般写在viewDidload的最上边
    // Observe:观察者
    // selector:只要一监听到通知,就会调用观察者这个方法
    // Name:通知名称
    // object:是谁发出的通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reciveNote:) name:@"note" object:nil];

// 监听到通知就会调用
- (void)reciveNote:(NSNotification *)notification
{
    // notification.userInfo是发送通知时传的参数
    NSLog(@"接收到通知");
}

// 一个对象即将销毁就会调用
- (void)dealloc
{
    // 一定要记得移除通知,否则有可能出现野指针的情况。
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}


  • 通过 -addObserverForName:object:queue:usingBlock: 方法接收通知

我还是更倾向于使用这个方法,接收通知后的处理逻辑代码写在block中,不用再去定义个方法,使用起来没那么麻烦。这个方法也是写在viewDidload的开头。需要注意的是,这个方法是有返回值的,由于方法中没有Observer这个参数,移除这个监听,我们需要自己定义一个参数作为观察者。
// 这个对象是系统管理的,因此使用 weak
@property (nonatomic, weak) NSObject *observer;

    // queue:The operation queue to which block should be added.
    //  If you pass nil, the block is run synchronously on the posting thread.
    _observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"note" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
        // note.userInfo是发送通知时传的参数
        NSLog(@"接收到通知");
    }];

// 一个对象即将销毁就会调用
- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:_observer];
}

通知与多线程的运用


  • -addObserver:selector:name:object:方法与多线程

在使用- addObserver:selector:name:object:方法与多线程结合时,处理逻辑代码(sel中的代码)所在线程,与发送通知的所在线程有关,与接收通知的方法(- addObserver:selector:name:object:方法)所在线程无关。发送通知在主线程,那么逻辑处理代码也在主线程;反之,发送通知代码在异步线程,那么逻辑代码也在异步线程。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 由于通知是在异步线程接收的,因此无法保证 接收通知在发送通知之前
        // 将发送通知代码写在-touchesBegan:withEvent 方法中,当用户点击屏幕后再发送通知,即可解决顺序问题
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNote:) name:@"note" object:nil];
    });

// 用户点击屏幕后再发送通知,即可实现 先接收通知,后发送通知的顺序
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    // 需要注意的是,如果只需要添加一次通知的话,需要定义一个bool进行下处理,否则每次点击屏幕,都会发送下通知。
    [[NSNotificationCenter defaultCenter] postNotificationName:@"note" object:nil];
}

- (void)receiveNote:(NSNotification *)note
{
    /*
        通过 - addObserver:selector:name:object:方法接收通知,接收通知逻辑代码的线程由发送通知的方法所处的线程决定。如果-postNotificationName:object:方法在主线程中,则逻辑处理方法也在主线程;反之,如果-postNotificationName:object:方法在异步线程,那么逻辑处理代码也在异步线程。与接收通知代码所在线程无关。
     */
    NSLog(@"%@",[NSThread currentThread]);
}

// 一个对象即将销毁就会调用
- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}


  • -addObserverForName:object:queue:usingBlock: 方法与多线程

当使用-addObserverForName:object:queue:usingBlock: 方法与多线程结合时,逻辑处理代码在block当中,逻辑处理代码所在线程与queue参数有关。推荐使用-addObserverForName:object:queue:usingBlock: 方法来接收通知,因为接收通知的线程可自己控制
@property (nonatomic, weak) NSObject *observer;

_observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"note" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
        // 通过该方法接收通知,逻辑处理代码所在线程与queue:参数有关。
        // 使用该方法的好处在于,可以自己控制逻辑代码所在线程
        NSLog(@"%@",[NSThread currentThread]);
    }];

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    // 需要注意的是,如果只需要添加一次通知的话,需要定义一个bool进行下处理,否则每次点击屏幕,都会发送下通知。
    [[NSNotificationCenter defaultCenter] postNotificationName:@"note" object:nil];
}


// 一个对象即将销毁就会调用
- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:_observer];
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值