首先 我们需要明确的是 是NSNotificationCenter的这个类的对象 发送NSNotification的对象
NSNotification的这个对象有三个属性
name : 通知的名称,
object : 发出的通知的那个对象
userInfo : 传递的参数,这个参数是字典,通知之间只能以字典的方式传递数据
创建一个通知,这个通知三个参数就是通知的属性
NSMutableDictionary * dict = [NSMutableDictionary dictionary];
dict[@"1"]=@"2";
dict[@"3"]=@"4";
NSNotification * noti = [[NSNotification alloc]initWithName:@"nicai" object:nil userInfo:dict];
不可以这样 因为 这三个参数 属性是readonly 是只读属性。只有get方法,没有set方法
NSNotification * noti1 = [[NSNotification alloc]init];
noti1.name = @"nicai";
noti1.object = nil;
noti1.userInfo = nil;
首先 通知中心 是单例 这个类方法提供快速创建通知中心的对象
NSNotificationCenter * center1 = [NSNotificationCenter defaultCenter];
NSNotificationCenter * center2 = [NSNotificationCenter defaultCenter];
NSLog(@"%@ %@",center1,center2);
两个是一模一样的
添加监听者 当通知中心发出通知时,oberver 会根据发出通知的对象object 和 通知的name 来决定是不是执行selector
两者都一样 就执行。
object若是空的话,name不为空 意味着 不管谁发出name的通知,这个监听者都会接收到通知并执行selector方法
若name是空的话 object不为空 只要这个object发出通知,他都会执行相应的selector的方法
[center1 addObserver:self selector:@selector(noti:) name:@"nicai" object:nil];
第一种方式 发出通知 noti是一个NSNotification类型
[center1 postNotification:noti];
第二种方式 发出通知,name是通知的名字,object是发出通知的对象
object若是空的话,只要有监听者收到name的通知,他们都会执行相应的selector的方法 无论是谁发出的
[center1 postNotificationName:@"nicai" object:self];
第三种方式 发出通知 name是通知的名字 object是发出通知的对象 userInfo是通知要传递的参数
[center1 postNotificationName:@"nicai" object:nil userInfo:nil];
-(void)noti:(NSNotification *)noti{
NSLog(@"传递过来的参数 %@",noti.userInfo);
NSLog(@"noti %@",noti);
}
在控制器销毁的时候 要移除观察者
-(void)dealloc{
NSNotificationCenter * center1 = [NSNotificationCenter defaultCenter];
移除观察者 在这个观察者所有的name下 都会移除,
[center1 removeObserver:self];
移除观察者观察的对应通知,
[center1 removeObserver:self name:nil object:nil];
}
接收通知失败的原因
一 ,先发通知,在添加观察者
有一些对通知理解不深的人,会犯这个错误,如以下写法 应该是先添加观察者,在发通知
[center1 postNotificationName:@"nicai" object:nil userInfo:nil];
[center1 addObserver:self selector:@selector(noti:) name:@"nicai" object:nil];
二,name不对,
一些不认真的人,有时候name少拼或者多拼 等等原因吧,让name不一样,那接收通知的肯定不会去执行相应的方法
[center1 addObserver:self selector:@selector(noti:) name:@"nicaia" object:nil];
[center1 postNotificationName:@"nicai" object:nil userInfo:nil];
三,object不对,
可能是程序的习惯吧,我们喜欢在发出通知 或者在接收通知的时候 把object都写成self
这个self如果你细心的话,在两个类中,一个添加观察者,一个发出通知,你会发现self地址是不一样的。
一般的话,我们在两个不相干的类里面都会把两个object设置为nil
除非在同一个控制器里面 我们可以设置为self
[center1 addObserver:self selector:@selector(noti:) name:@"nicaia" object:nil];
[center1 postNotificationName:@"nicai" object:nil userInfo:nil];
四,没有注册通知
我记得在iOS8 之下,要在AppDelegate里面要去注册通知
//注册本地通知
if (iOS8) { // ios8才需要注册通知
UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];
[application registerUserNotificationSettings:setting];
}
鉴于我对于通知的理解,我给大家提点我的看法
在一个项目里面,你的通知的名字,用一个专门的.h文件来记录,并且每一个name都要自释义,就是别人一拿到你的name 就知道你要干嘛,另外,在.h里面 如果通知的name你自释义感觉不靠谱的话,尽量用语言来描述
对于传值的话,如果两个类没有多大联系,你可以用通知来传递,如果有关系,比如a push到b 或者b pop 到a 这些传值是很方便的顺传直接赋值,回传用代码块更方便。另外,用通知传递参数的比较少,可能主要原因是通知的参数不是太容易看出来吧。所以,我们传值能少用通知,就少用通知吧