NSNotificationCenter的使用详解
通常我们在 iOS 中发生什么事件时该做什么是由 Delegate 实现的,例如 View 加载完后会触发 viewDidLoad。Apple 还为我们提供了另一种通知响应方式,那就是 NSNotification,系统中(UIKeyboardDidShowNotification 等) 以及某些第三方组件(例如 ASIHTTPRequest 的 kReachabilityChangedNotification 等)。
NSNotificationCenter 较之于 Delegate 可以实现更大的跨度的通信机制,可以为两个无引用关系的两个对象进行通信。NSNotificationCenter 的通信原理使用了观察者模式:
- NSNotificationCenter 注册观察者对某个事件(以字符串命名)感兴趣,及该事件触发时该执行的 Selector 或 Block
- NSNotificationCenter 在某个时机激发事件(以字符串命名)
- 观察者在收到感兴趣的事件时,执行相应的 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一般都写主队列