iOS之NSNotificationCenter通知中心使用事项
其实这里的通知和之前说到的KVO功能很想,也是用于监听操作的,但是和KVO不同的是,KVO只用来监听属性值的变化,这个发送监听的操作是系统控制的,我们控制不了,我们只能控制监听操作,类似于Android中系统发送的广播,我们只能接受。但是通知就不一样了,他的监听发送也是又我们自己控制,我们可以在任何地方任何时机发送一个通知,类似于Android中开发者自己发送的广播。从这一点看来,通知的使用场景更为广泛了。
下面就来看一下例子:
还是护士和小孩的那个例子
Children.h
- //
- // Children.h
- // 44_KVO
- //
- // Created by jiangwei on 14-10-16.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- @interface Children : NSObject
- @property NSInteger *hapyValue;
- @end
定义了一个属性:hapyValue
Children.m
- //
- // Children.m
- // 44_KVO
- //
- // Created by jiangwei on 14-10-16.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import "Children.h"
- @implementation Children
- - (id) init{
- self = [super init];
- if(self != nil){
- //启动定时器
- [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
- self.hapyValue= 100;
- }
- return self;
- }
- - (void) timerAction:(NSTimer *) timer{
- //使用set方法修改属性值,才能触发KVO
- _hapyValue--;
- NSLog(@"%@",_hapyValue);
- if(_hapyValue <80){
- //发送通知
- //这里和KVO的区别,我们可以手动的发送通知
- //注意通知的名称,传递的参数必须和定义通知的地方的参数值要一致
- //将Children对象传递过去
- [[NSNotificationCenter defaultCenter] postNotificationName:@"happyValueNotification" object:self];
- }
- }
- @end
定义了一个定时器,但是我们看到这里的timerAction方法中就开始发送一个通知了:
- //发送通知
- //这里和KVO的区别,我们可以手动的发送通知
- //注意通知的名称,传递的参数必须和定义通知的地方的参数值要一致
- //将Children对象传递过去
- [[NSNotificationCenter defaultCenter] postNotificationName:@"happyValueNotification" object:self];
我们在属性值发生变化的地方发送一个通知:NSNotificationCenter
第一个参数:通知的名称,这个名称必须和后面接受通知的名称一致
第二个参数:可以传递的一个参数对象
Nure.h
- //
- // Nure.h
- // 44_KVO
- //
- // Created by jiangwei on 14-10-16.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- @interface Nure : NSObject
- @end
Nure.m
- //
- // Nure.m
- // 44_KVO
- //
- // Created by jiangwei on 14-10-16.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import "Nure.h"
- #import "Children.h"
- @implementation Nure
- - (id) init{
- self = [super init];
- if(self != nil){
- //监听一个通知,当收到通知时,调用notificationAction方法
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationAction) name:@"happyValueNotification" object:nil];
- }
- return self;
- }
- - (void) notificationAction:(NSNotification *)notification{
- //这里我们拿到Children对象进行操作
- Children *children = notification.object;
- NSLog(@"触发通知");
- }
- - (void)dealloc{
- //移除指定的通知,不然会造成内存泄露
- [[NSNotificationCenter defaultCenter] removeObserver:self name:@"happyValueNotification" object:nil];
- //Children对象可以添加多个通知
- //下面的方法是可以移除Children中所有通知
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- }
- @end
在Nure类中我们开始接受通知了:
- //监听一个通知,当收到通知时,调用notificationAction方法
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationAction) name:@"happyValueNotification" object:nil];
使用addObserver方法来监听通知
第一个参数:监听者对象
第二个参数:监听处理逻辑的方法
第三个参数:通知的名称
第四个参数:通知发送的时候传递过来的参数对象
1、处理通知的方法
- - (void) notificationAction:(NSNotification *)notification{
- //这里我们拿到Children对象进行操作
- Children *children = notification.object;
- NSLog(@"触发通知");
- }
这
里会传递一个NSNotification对象,通过object属性可以获取到监听对象了,因为我们在发送通知的时候传递过来的这个对象。那么这里我们
就可以获取监听对象的属性值了,但是这里我们如果想知道属性值变化前和变化后的值,我们可以在Children类中在定义一个属性专门用来记录旧的属性
值,这样就可以了。
2、销毁方法
- - (void)dealloc{
- //移除指定的通知,不然会造成内存泄露
- [[NSNotificationCenter defaultCenter] removeObserver:self name:@"happyValueNotification" object:nil];
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- }
在销毁的方法中,我们可以需要移除监听者,传递过去通知名
但是这里我们会注意到,还有一个方法:removeObserver方法,是用来移除所有监听者的,因为可能有多个监听者。
总结
OC中KVO操作和通知都是很重要的一个操作,他们的原理是基于观察者模式的,但是KVO操作没有通知灵活。但是KVO也有自己的优点,比如可以记录新旧值,这个通知就比较麻烦点了,所以我们在使用的时候视情况而定,一般监听属性值变化的我们还是使用KVO.
使用过程中需要注意的几点事项:
一、了解几个相关的类
1、NSNotification
这个类可以理解为一个消息对象,其中有三个成员变量。
这个成员变量是这个消息对象的唯一标识,用于辨别消息对象。
@property (readonly, copy) NSString *name;
这个成员变量定义一个对象,可以理解为针对某一个对象的消息。
@property (readonly, retain) id object;
这个成员变量是一个字典,可以用其来进行传值。
@property (readonly, copy) NSDictionary *userInfo;
NSNotification的初始化方法:
- (instancetype)initWithName:(NSString *)name object:(id)object userInfo:(NSDictionary *)userInfo;
+ (instancetype)notificationWithName:(NSString *)aName object:(id)anObject;
+ (instancetype)notificationWithName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
注意:官方文档有明确的说明,不可以使用init进行初始化
2、NSNotificationCenter
这个类是一个通知中心,使用单例设计,每个应用程序都会有一个默认的通知中心。用于调度通知的发送的接受。
添加一个观察者,可以为它指定一个方法,名字和对象。接受到通知时,执行方法。
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
发送通知消息的方法
- (void)postNotification:(NSNotification *)notification;
- (void)postNotificationName:(NSString *)aName object:(id)anObject;
- (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
移除观察者的方法
- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;
二、通知的使用流程
首先,我们在需要接收通知的地方注册观察者,比如:
//获取通知中心单例对象
NSNotificationCenter * center = [NSNotificationCenter defaultCenter];
//添加当前类对象为一个观察者,name和object设置为nil,表示接收一切通知
[center addObserver:self selector:@selector(notice:) name:@"123" object:nil];
之后,在我们需要时发送通知消息
//创建一个消息对象
NSNotification * notice = [NSNotification notificationWithName:@"123" object:nil userInfo:@{@"1":@"123"}];
//发送消息
[[NSNotificationCenter defaultCenter]postNotification:notice];
我们可以在回调的函数中取到userInfo内容,如下:
-(void)notice:(id)sender{
NSLog(@"%@",sender);
}
三、多线程通知
首先看下苹果的官方说明:
Regular notification centers deliver notifications on the thread in which the notification was posted. Distributed notification centers deliver notifications on the main thread. At times, you may require notifications to be delivered on a particular thread that is determined by you instead of the notification center. For example, if an object running in a background thread is listening for notifications from the user interface, such as a window closing, you would like to receive the notifications in the background thread instead of the main thread. In these cases, you must capture the notifications as they are delivered on the default thread and redirect them to the appropriate thread.
意思很简单,NSNotificationCenter消息的接受线程是基于发送消息的线程的。也就是同步的,因此,有时候,你发送的消息可能不在主线程,而大家都知道操作UI必须在主线程,不然会出现不响应的情况。所以,在你收到消息通知的时候,注意选择你要执行的线程。下面看个示例代码
//接受消息通知的回调
- (void)test
{
if ([[NSThread currentThread] isMainThread]) {
NSLog(@"main");
} else {
NSLog(@"not main");
}
dispatch_async(dispatch_get_main_queue(), ^{
//do your UI
});
}
//发送消息的线程
- (void)sendNotification
{
dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(defaultQueue, ^{
[[NSNotificationCenter defaultCenter] postNotificationName:@"test" object:nil];
});
}
iOS之NSNotificationCenter通知中心使用事项的更多相关文章
- iOS 设计模式-NSNotificationCenter 通知中心
通知介绍 每一个应用程序都有一个通知中心(NSNotificationCenter)实例,专门负责协助不同对象之间的消息通信 任何一个对象都可以向通知中心发布通知(NSNotification),描述 ...
- NSNotificationCenter通知中心
概述 NSNotificationCenter通知中心,通常用于一对一或者一对多的消息传递,即当一个地方改变时,要求改变其他的一些地方,例如当网络请求回来了新的数据,需要刷新本地信息和本地内存里面的界 ...
- iOS开发之通知中心(NSNotificationCenter)
前言 面向对象的设计思想是把行为方法封装到每一个对象中,以用来增加代码的复用性.正是这种分散封装,增加了对象之间的相互关联,总是有很多的对象需要彼此了解以及相互操作! 一个简单示例说明这种交互产生的对 ...
- iOS生命周期 & 通知中心
笔记内容 学习笔记-段玉磊 Stanford course View Controller Lifecycle 这篇文是我记载Developing iOS 7 Apps公开课 第5课的笔记 UITex ...
- IOS NSNotification Center 通知中心的使用
通知中心,它是IOS程序内部的一种消息广播机制,通过它,可以实现无引用关系的对象之间的通信.通知中心他是基于观察者模式,它只能进行程序内部通信,不能跨应用程序进程通信.当通知中心接受到消息后会根据设置 ...
- NSNotificationCenter 通知中心传值
1.NSNotification 这个类可以理解为一个消息对象,其中有三个成员变量. 这个成员变量是这个消息对象的唯一标识,用于辨别消息对象. @property (readonly, copy) N ...
- iOS 通知中心 NSNotificationCenter
iOS开发中,每个app都有一个通知中心,通知中心可以发送和接收通知. 在使用通知中心 NSNotificationCenter之前,先了解一下通知 NSNotification. NSNotific ...
- 通知中心 NSNotificationCenter 的简单使用方法
NSNotificationCenter(通知中心) [注意]需再dealloc中移除观察者 获取通知中心单例对象 NSNotificationCenter *center=[NSNotifi ...
- 通知中心 NSNotificationCenter
NSNotificationCenter 通知中心提供了一种在程序内广播信息的途径,一个NSNotificationCenter对象本质上是一个通知分发表(notification dispatch ...
随机推荐
- Oracle MySQL Server 安全漏洞
漏洞名称: Oracle MySQL Server 安全漏洞 CNNVD编号: CNNVD-201401-317 发布时间: 2014-01-22 更新时间: 2014-01-22 危害等级: 中危 ...
- vpn分配多ip的配置
1,创建vpn路由和远程访问 --配置并启用和路由远程访问--自定义配置--选择“vpn访问”,“nat和基本防火墙. 2,vpn配置ip路由选择(nat/基本防火墙)--新增接口(选择本地网卡)-- ...
- lightoj 1011 (状态压缩dp)
思路:状态压缩dp,设dp[i][j] 表示前i行,状态为j时的最大值,状态定义为:若前i行中取了第x列那么j的二进制位中第x位为1,否则为0,最后答案就是dp[n-1][(1 << n) ...
- [BILL WEI] SQL 巧用临时表
在写sql 的时候,我们有时候,只需要拿出某些特定的数据,去跟一些表进行关联,但是如果直接通过表关联的话,可能拿到 的数据有冗余,这个时候,我们就可以巧用临时表,讲自己需要的特定数据筛选出来,然后组成 ...
- Entity Framework 杂碎
其实看图很简单,database first和model first都是通过 data model创建的edmx文件,只不过model first模块可以自己根据需要创建和修改实体,显得更加灵活. c ...
- java md5方法 for Android
很简单的方法 public static String md5(String string) { byte[] hash; try { hash = MessageDigest.getInstance ...
- ACM编程技巧--代码片段
验证n是否是完全平方数 #include<math.h> double m=sqrt(n); if(floor(m+0.5)==m) printf("%d是完全平方数.\n&qu ...
- HW5.24
import java.util.Calendar; public class Solution { public static void main(String[] args) { System.o ...
- HDU 3392 Pie(DP)
题意:有一些男生女生,男生女生数量差不超过100 ,男生女生两两配对.要求求出一种配对方法,使每一对的高度差的和最小. 思路:(我是真的笨笨笨!!)设人少的一组人数为n,b[],人多的一组人数为m,g ...
- 问题-[Delphi]在对GRID设置单击为编辑时,其他GRID可以,但有一个GRID不行?
问题现象:在对GRID设置单击为编辑时,其他GRID可以,但有一个GRID不行?问题原因:在这个GRID中的单击事件可能不存在,可以测试一下有没有单击事件.解决方法:需要在GRID的上一个类中,放开单 ...