NSNotificationCenter的使用详解

通常我们在 iOS 中发生什么事件时该做什么是由 Delegate 实现的,例如 View 加载完后会触发 viewDidLoad。Apple 还为我们提供了另一种通知响应方式,那就是 NSNotification,系统中(UIKeyboardDidShowNotification 等) 以及某些第三方组件(例如 ASIHTTPRequest 的 kReachabilityChangedNotification 等)。

NSNotificationCenter 较之于 Delegate 可以实现更大的跨度的通信机制,可以为两个无引用关系的两个对象进行通信。NSNotificationCenter 的通信原理使用了观察者模式:

  1. NSNotificationCenter 注册观察者对某个事件(以字符串命名)感兴趣,及该事件触发时该执行的 Selector 或 Block
  2. NSNotificationCenter 在某个时机激发事件(以字符串命名)
  3. 观察者在收到感兴趣的事件时,执行相应的 Selector 或 Block

使用 NSNotificationCenter 的步骤示例代码:

  • 注册观察者:
[[NSNotificationCenter defaultCenter] addObserver:观察者 selector:@selector(execute:) name:@"消息的名称" object:消息的发布者];

// 如果objct为nil,则只根据消息名称收消息,而不关心发布者
//如果name为nil,则只关心发布者,而不关心发的什么消息
//如果object和name都为nil,就表示什么消息都接收
  • 定义一个事件到来时该执行的方法:
- (void)execute:(NSNotification *)notification {
     //当收到某个消息后做什么事情
     //如果收到notification.name为@"消息的名称"
     if(notification.object && [notification.object isKindOfClass:[Test class]]){
         //可以根据消息的发出者来判断是否对消息做相应处理
     }
}
  • 激发事件,即通知相应的观察者
[[NSNotificationCenter defaultCenter] postNotificationName:@"NOTIFICATION_NAME" object:nil];

//使用userInfo可以传递一些内容
[[NSNotificationCenter defaultCenter] postNotificationName:@"NOTIFICATION_NAME" object:nil userInfo:@{字典}];

//或者用下面几行代码,明确的 notification 示例
Test *test = [[Test alloc] init];
NSNotification *notification = [NSNotification notificationWithName:@"NOTIFICATION_NAME" object:test];

//[NSNotification notificationWithName:@"NOTIFICATION_NAME" object:test userInfo:@{字典}]

[[NSNotificationCenter defaultCenter] postNotification:notification];
  • 移除监听,移除观察者
[[NSNotificationCenter defaultCenter] removeObserver:观察者 name:@"消息的名称" object:消息的发布者];

//或者
[[NSNotificationCenter defaultCenter] removeObserver:观察者];

多线程监听方式

#import "ViewController.h"

@interface ViewController ()
/**
    UIScrollVIew要做自动布局,首先确定scrollView滚动范围
    如何在storyboard对scrollView定义滚动范围
    可以添加一个UIView来确定scrollView的滚动范围

    如何确定水平和垂直方向:

    scrollView 水平是否能滚动:View的宽度 + 左右两边的间距 来确定scrollView的水平滚动范围
    scrollView 垂直是否能滚动:View的高度 + 上下两边的间距 来确定scrollView的垂直滚动范围
 **/
@property (strong, nonatomic) IBOutlet UIScrollView *scrollVIew;

@property(weak,nonatomic)id observer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    //在队列中监听消息
    self.observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"note" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
        NSLog(@"%@",[NSThread currentThread]);
    }];

    //发出消息
    [[NSNotificationCenter defaultCenter] postNotificationName:@"note" object:nil];
}

//一定要在对象移除的时候取消监听
- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self.observer name:@"note" object:nil];
}

@end

注意:

在子线程监听通知,主线程发出通知,那么接收通知的代码会在主线程中执行

在主线程监听通知,子线程发出通知,那么接收通知的代码会在子线程中执行,如果还需要更新UI,则还需要回到主线程,所以

[[NSNotificationCenter defaultCenter] addObserverForName:@"note" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
        NSLog(@"%@",[NSThread currentThread]);
    }];

//其中的queue一般都写主队列

results matching ""

    No results matching ""