ios--->ios消息机制(NSNotification 和 NSNotificationCenter)
问题的背景
- IOS中委托模式和消息机制基本上开发中用到的比较多,一般最开始页面传值通过委托实现的比较多,类之间的传值用到的比较多,不过委托相对来说只能是一对一,比如说页面A跳转到页面B,页面的B的值改变要映射到页面A,页面C的值改变也需要映射到页面A,那么就需要需要两个委托解决问题。NSNotificaiton则是一对多注册一个通知,之后回调很容易解决以上的问题。
概念
iOS消息通知机制算是同步的,观察者只要向消息中心注册, 即可接受其他对象发送来的消息,消息发送者和消息接受者两者可以互相一无所知,完全解耦。这种消息通知机制可以应用于任意时间和任何对象,观察者可以有多个,所以消息具有广播的性质,只是需要注意的是,观察者向消息中心注册以后,在不需要接受消息时需要向消息中心注销,属于典型的观察者模式。
消息通知中重要的两个类:
(1)NSNotificationCenter: 实现NSNotificationCenter的原理是一个观察者模式,获得NSNotificationCenter的方法只有一种,那就是[NSNotificationCenter defaultCenter] ,通过调用静态方法defaultCenter就可以获取这个通知中心的对象了。NSNotificationCenter是一个单例模式,而这个通知中心的对象会一直存在于一个应用的生命周期。
(2) NSNotification: 这是消息携带的载体,通过它,可以把消息内容传递给观察者。
使用
- 1.通过NSNotificationCenter注册通知NSNotification,viewDidLoad中代码如下:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationFirst:) name:@"First" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationSecond:) name:@"Second" object:nil];
第一个参数是观察者为本身,第二个参数表示消息回调的方法,第三个消息通知的名字,第四个为nil表示表示接受所有发送者的消息~
回调方法:
-(void)notificationFirst:(NSNotification *)notification{
NSString *name=[notification name];
NSString *object=[notification object];
NSLog(@"名称:%@----对象:%@",name,object);
}
-(void)notificationSecond:(NSNotification *)notification{
NSString *name=[notification name];
NSString *object=[notification object];
NSDictionary *dict=[notification userInfo];
NSLog(@"名称:%@----对象:%@",name,object);
NSLog(@"获取的值:%@",[dict objectForKey:@"key"]);
}
- 2.消息传递给观察者
[[NSNotificationCenter defaultCenter] postNotificationName:@"First" object:@"博客园-Fly_Elephant"];
NSDictionary *dict=[[NSDictionary alloc]initWithObjects:@[@"keso"] forKeys:@[@"key"]];
[[NSNotificationCenter defaultCenter] postNotificationName:@"Second" object:@"http://www.cnblogs.com/xiaofeixiang" userInfo:dict];
- 3.销毁观察者
-(void)dealloc{
NSLog(@"观察者销毁了");
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
也可以通过name单个删除:
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"First" object:nil];
- 4.运行结果
2015-04-26 15:08:25.900 CustoAlterView[2169:148380] 观察者销毁了
2015-04-26 15:08:29.222 CustoAlterView[2169:148380] 名称:First----对象:博客园-Fly_Elephant
2015-04-26 15:08:29.222 CustoAlterView[2169:148380] 名称:Second----对象:http://www.cnblogs.com/xiaofeixiang
2015-04-26 15:08:29.223 CustoAlterView[2169:148380] 获取的值:keso
深入分析观察者
- 如果想让对象监听某个通知,则需要在通知中心中将这个对象注册为通知的观察者。早先,NSNotificationCenter提供了以下方法来添加观察者:
- (void)addObserver:(id)notificationObserver selector:(SEL)notificationSelector name:(NSString *)notificationName object:(id)notificationSender
这个方法带有4个参数,分别指定了通知的观察者、处理通知的回调、通知名及通知的发送对象。这里需要注意几个问题
notificationObserver不能为nil。
notificationSelector回调方法有且只有一个参数(NSNotification对象)。
如果notificationName为nil,则会接收所有的通知(如果notificationSender不为空,则接收所有来自于notificationSender的所有通知)。如代码清单1所示。
如果notificationSender为nil,则会接收所有notificationName定义的通知;否则,接收由notificationSender发送的通知。
监听同一条通知的多个观察者,在通知到达时,它们执行回调的顺序是不确定的,所以我们不能去假设操作的执行会按照添加观察者的顺序来执行。
对于以上几点,我们来重点关注一下第3条。以下代码演示了当我们的notificationName设置为nil时,通知的监听情况。
测试代码如下
添加一个Observer,其中notificationName为nil
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:nil object:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:TEST_NOTIFICATION object:nil];
}
- (void)handleNotification:(NSNotification *)notification
{
NSLog(@"notification = %@", notification.name);
}
@end
运行后的输出结果如下:
notification = TestNotification
notification = UIWindowDidBecomeVisibleNotification
notification = UIWindowDidBecomeKeyNotification
notification = UIApplicationDidFinishLaunchingNotification
notification = _UIWindowContentWillRotateNotification
notification = _UIApplicationWillAddDeactivationReasonNotification
notification = _UIApplicationDidRemoveDeactivationReasonNotification
notification = UIDeviceOrientationDidChangeNotification
notification = _UIApplicationDidRemoveDeactivationReasonNotification
notification = UIApplicationDidBecomeActiveNotification
可以看出,我们的对象基本上监听了测试程序启动后的所示消息。当然,我们很少会去这么做。
而对于第4条,使用得比较多的场景是监听UITextField的修改事件,通常我们在一个ViewController中,只希望去监听当前视图中的UITextField修改事件,而不希望监听所有UITextField的修改事件,这时我们就可以将当前页面的UITextField对象指定为notificationSender。
NSNotification Block
在iOS 4.0之后,NSNotificationCenter为了跟上时代,又提供了一个以block方式实现的添加观察者的方法,如下所示:
- (id)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block
大家第一次看到这个方法时是否会有这样的疑问:观察者呢?参数中并没有指定具体的观察者,那谁是观察者呢?实际上,与前一个方法不同的是,前者使用一个现存的对象作为观察者,而这个方法会创建一个匿名的对象作为观察者(即方法返回的id对象),这个匿名对象会在指定的队列(queue)上去执行我们的block。
这个方法的优点在于添加观察者的操作与回调处理操作的代码更加紧凑,不需要拼命滚动鼠标就能直接找到处理代码,简单直观。这个方法也有几个地方需要注意:
name和obj为nil时的情形与前面一个方法是相同的。
如果queue为nil,则消息是默认在post线程中同步处理,即通知的post与转发是在同一线程中;但如果我们指定了操作队列,情况就变得有点意思了,我们一会再讲。
block块会被通知中心拷贝一份(执行copy操作),以在堆中维护一个block对象,直到观察者被从通知中心中移除。所以,应该特别注意在block中使用外部对象,避免出现对象的循环引用,这个我们在下面将举例说明。
如果一个给定的通知触发了多个观察者的block操作,则这些操作会在各自的Operation Queue中被并发执行。所以我们不能去假设操作的执行会按照添加观察者的顺序来执行。
该方法会返回一个表示观察者的对象,记得在不用时释放这个对象。
下面我们重点说明一下第2点和第3点。
ios--->ios消息机制(NSNotification 和 NSNotificationCenter)的更多相关文章
- iOS开发-消息通知机制(NSNotification和NSNotificationCenter)
iOS中委托模式和消息机制基本上开发中用到的比较多,一般最开始页面传值通过委托实现的比较多,类之间的传值用到的比较多,不过委托相对来说只能是一对一,比如说页面A跳转到页面B,页面的B的值改变要映射到页 ...
- 消息通知机制(NSNotification和NSNotificationCenter)
作者:FlyElephant 出处:http://www.cnblogs.com/xiaofeixiang iOS中委托模式和消息机制基本上开发中用到的比较多,一般最开始页面传值通过委托实现的比较多, ...
- ios消息机制
ios消息机制介绍 ios 调用每一个方法的时候其实是走的ios的消息机制 举例介绍一下 创建一个Pserson类 有一个eat 对象方法 那么下面的代码可以用消息机制实现 导入消息头文件 # ...
- IOS 消息机制(NSNotificationCenter)
消息机制 NSNotificationCenter 一直都在频繁使用,但是却对其原理不是十分了解.今天就花些时间,把消息机制原理重头到尾好好过一遍. iOS 提供了一种 "同步的" ...
- iOS NSNotificationCenter(消息机制)
转自:http://blog.csdn.net/liliangchw/article/details/8276803 对象之间进行通信最基本的方式就是消息传递,在Cocoa中提供Notificatio ...
- iOS开发系列--通知与消息机制
概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知机制就可以告诉用户此时发生的事情.iOS中通知机制又叫消息机制,其包括两类:一类是本地 ...
- iOS开发系列--通知与消息机制--转
来自:http://www.cocoachina.com/ios/20150318/11364.html 概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户 ...
- IOS开发-通知与消息机制
在多数移动应用中不论什么时候都仅仅能有一个应用程序处于活跃状态.假设其它应用此刻发生了一些用户感兴趣的那么通过通知机制就能够告诉用户此时发生的事情. iOS中通知机制又叫消息机制,其包含两类:一类是本 ...
- iOS的消息转发机制详解
iOS开发过程中,有一类的错误会经常遇到,就是找不到所调用的方法,当然这类问题比较好解决,给当前对象或其父类对象添加该方法即可,使得编译器在编译时能正确找到该方法:或者,还有另外的方法,由于Objec ...
随机推荐
- 修改Samba密码后无法登录
Samba修改用户名密码后,无法登陆 之后每次进去都是以这样的username和passwd进去的,如何才能使用其他的用户来重新登录samba server呢? 首先使用在开始菜单里面输入cmd: 进 ...
- .NET进阶篇07-.NET和COM
知识需要不断积累.总结和沉淀,思考和写作是成长的催化剂 内容目录 一.COM和.NET元数据内存管理接口注册线程编组二..NET客户端调用COM组件三.COM客户端调用.NET组件四.嵌入互操作类型五 ...
- RobotFramework+Appium 为了兼容iOS12,升级至Xcode10后,WebDriverAgent编译不通过:Undefind symbols for architecture x86_64
报错信息如下: Undefined symbols for architecture arm64: "_OBJC_CLASS_$_XCElementSnapshot", refer ...
- Spring Boot 整合 slf4j+log4j2 实现日志管理
背景 Java 中比较常用的日志框架: log4j(Log for Java):Apache 的一个开源项目,七种日志级别:OFF.FATAL.ERROR.WARN.INFO.DEBUG.TRACE ...
- BeetleX之XRPC使用详解
XRPC是基于BeetleX扩展一个远程接口调用组件,它提供基于接口的方式来实现远程服务调用,在应用上非常简便.组件提供.NETCore2.1和.NETStandard2.0的client版本,因此即 ...
- k8s 开船记-故障公告:自建 k8s 集群在阿里云上大翻船
非常非常抱歉,新年上班第一天, 在今天阿里云上气候突变情况下,由于我们开船技术差,在今天 10:15~12:00 左右的访问高峰,我们竟然把船给开翻了,造成近2个小时整个博客站点无法访问,由此给您带来 ...
- mysqldump主从复制
一,主从复制条件 1,开启binlog功能2,主库建立同步账号3,从库配置master.info(change mast..)4,start slave复制开关知识点:####1, 3个线程,主库i ...
- 【题解】歌唱王国(概率生成函数+KMP)+伦讲的求方差
[题解]歌唱王国(概率生成函数+KMP)+伦讲的求方差 生成函数的本质是什么呀!为什么和It-st一样神 设\(f_i\)表示填了\(i\)个时候停下来的概率,\(g_i\)是填了\(i\)个的时候不 ...
- 使用Django进行后端开发
目录 更换pip源 搭建虚拟环境 项目目录设置 项目相关配置 更换pip源 更换pip源 搭建虚拟环境 搭建虚拟开发环境 项目目录设置 项目目录设置 项目相关配置 项目相关配置
- selenium模块的基本使用
一.selenium库与requests库的区别 - selenium请求库: - 本质上是一个自动化测试模块; ---> 主要用于测试 UI界面 - selenium除了可以做自动化测试,还可 ...