NSNotification

对象间信息传递的标准方式是消息,发送消息的对象要知道消息的接受者,是一对一发送的。在iOS系统下,通过广播机制来达到这个目的,对象向通知中心(NSNotificationCenter)投递一个通知,由通知中心将其收到的通知分发给“感兴趣”的接收者。通知中心的原理非常符合设计模式中的观察者(Observer)模式。

 什么是Notification?这个要求其实也很容易实现. 每个运行中的application都有一个NSNotificationCenter的成员变量,它的功能就类似公共栏. 对象注册关注某个确定的notification(如果有人捡到一只小狗,就去告诉我). 我们把这些注册对象叫做 observer. 其它的一些对象会给center发送notifications(我捡到了一只小狗). center将该notifications转发给所有注册对该notification感兴趣的对象. 我们把这些发送notification的对象叫做poster。很多的标准Cocoa类会发送notifications: 在改变size的时候,Window会发送notification; 选择table view中的一行时,table view会发送notification;我们可以在在线帮助文档中查看到标准cocoa对象发送的notification

在对象释放前,我们必须从notification center移除我们注册的observer. 一般我们在dealloc方法中做这件事

1、delegate与通知的不同
(1)delegate是一对一进行通信,接受者可以将返回值给sender,而通知是一对多,切不再需要返回值。
( 2)Delegate:消息的发送者(sender)告知接收者(receiver)某个事件将要发生,delegate同意然后发送者响应事件,delegate机制使得接收者可以改变发送者的行为。通常发送者和接收者的关系是直接的一对多的关系。
  Notification:
消息的发送者告知接收者事件已经发生或者将要发送,仅此而已,发送通知的对象甚至不知道是否消息的响应者observers是否存在接收者并不能反过来影响发送者的行为。通常发送者和接收者的关系是间接的多对多关系。
2通知中心的分类
(1)NSNotificationCenter 单进程通知管理
(2)NSDistributedNotificationCenter 一台机器中多进程的通知管理。
3、机制
在进程中有一个称为通告中心的对象,充当通告的信息交换和广播中心。在应用程序的其它地方,需要知道某 个事件的对象在通告中心进行注册,让它知道当该事件发生时,自己希望得到通知。这种场景的一个例子是当一个弹出式菜单被选择时,控制器对象需要知道这个事 件,以便在用户界面上对反映这个变化。当事件发生时,处理该事件的对象向通告中心发出一个通告,然后通告中心会将它派发给所有的相关的观察者。每个进程都包含一个默认的通知中心,通过[NSNotificationCentert defaultCenter]获取;通知中心分发给观察者处理采用同步机制。当某一对象发送一个通知时,会一直阻塞在发送方法内,直到通知中心将该通知分发给所有观察者并且全部处理成功返回后,发送者才能执行其所在线程内的后续代码。如需异步通知,参考官方文档。
4、使用
如果在一个类中想要执行另一个类中的方法可以使用通知
1.)创建一个通知对象:使用notificationWithName:object: 或者 notificationWithName:object:userInfo:
    NSNotification* notification = [NSNotification notificationWithName:kImageNotificationLoadFailed(connection.imageURL)
                                                                 object:self
                                                               userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error,@”error”,connection.imageURL,@”imageURL”,nil]];
这 里需要注意的是,创建自己的通知并不是必须的。而是在创建自己的通知之前,采用NSNotificationCenter类的方 法 postNotificationName:object: 和 postNotificationName:object:userInfo:更加便利的发出通知。这种情况,一般使用NSNotificationCenter的类方法defaultCenter就获得默认的通知对象,这样你就可以给该程序的默认通知中心发送通知了。注意:每一个程序都有一个自己的通知中心,即NSNotificationCenter对象。该对象采用单例设计模式,采用defaultCenter方法就可以获得唯一的NSNotificationCenter对象。
注意:NSNotification对象是不可变的,因为一旦创建,对象是不能更改的。
2.注册通知:addObserver:selector:name:object:
可以看到除了添加观察者之外,还有其接收到通知之后的执行方法入口,即selector的实参。因此为了进行防御式编程,最好先检查观察者是否定义了该方法。例如:添加观察者代码有
[[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(aWindowBecameMain:)
    name:NSWindowDidBecomeMainNotification object:nil];
这里保证了self定义了aWindowBecameMain:方法。而对于一个任意的观察者observer,不能保证其对应的selector有aWindowBecameMain:,可采用[observer respondsToSelector:@selector(aWindowBecameMain:)]] 进行检查。所以完整的添加观察者过程为:
if([observer respondsToSelector:@selector(aWindowBecameMain:)]) {
        [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(aWindowBecameMain:) name:NSWindowDidBecomeMainNotification object:nil];
    }
注 意到addObserver:selector:name:object:不仅指定一个观察者,指定通知中心发送给观察者的消息,还有接收通知的名字,以 及指定的对象。一般来说不需要指定name和object,但如果仅仅指定了一个object,观察者将收到该对象的所有通知。例如将上面的代码中 name改为nil,那么观察者将接收到object对象的所有消息,但是确定不了接收这些消息的顺序。如果指指定一个通知名称,观察者将收到它每次发出 的通知。例如,上面的代码中object为nil,那么客户对象(self)将收到任何对象发出NSWindowDidBecomeMainNotification通知。如果既没有指定指定object,也没有指定name,那么该观察者将收到所有对象的所有消息。
3.发送通知:postNotificationName:object:或者performSelectorOnMainThread:withObject:waitUntilDone:
例如程序可以实现将一个文本可以进行一系列的转换,例如对于一个实例、RTF格式转换成ASCII格式。而转换在一个类(如Converter类)的对象中得到处理,在诚寻执行过程中可以加入或者删除这种转换。而且当添加或者删除Converter操作时,你的程序可能需要通知其他的对象,但是这些Converter对象并不需要知道被通知对象是什么,能干什么。你只需要声明两个通知,”ConverterAdded” 和 “ConverterRemoved”,并且在某一事件发生时就发出这两个通知。
当一个用户安装或者删除一个Converter,它将发送下面的消息给通知中心:
[[NSNotificationCenter defaultCenter]
    postNotificationName:@”ConverterAdded” object:self];
或者是
[[NSNotificationCenter defaultCenter]
    postNotificationName:@”ConverterRemoved” object:self];
通知中心将会区分它们对象对这些通知是否感兴趣并且通知他们。如果除了关心观察者的通知名称和观察的对象,还关心其他之外的对象,那么就把之外的对象放在通知的可选字典中,或者用方法postNotificationName:object:userInfo:。
而采用performSelectorOnMainThread:withObject:waitUntilDone:则是直接调用NSNotification的方法postNotification,而postNotificationName和object参数可以放到withObject的实参中。例如:
[[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:YES];//注意这里的notification为自定义的一个通知对象,可定义为NSNotification* notification = [NSNotification notificationWithName:@”ConverterAdded”object:self];//那么它的作用与上面的一致
4.移除通知:removeObserver:和removeObserver:name:object:
其中,removeObserver:是删除通知中心保存的调度表一个观察者的所有入口,而removeObserver:name:object:是删除匹配了通知中心保存的调度表中观察者的一个入口。
这个比较简单,直接调用该方法就行。例如:
[[NSNotificationCenter defaultCenter] removeObserver:observer name:nil object:self];
注意参数notificationObserver为要删除的观察者,一定不能置为nil。

你可能感兴趣的:(ios)