NSNotificationCenter

来源:互联网 发布:数码宝贝网络侦探攻略 编辑:程序博客网 时间:2024/06/07 19:56

如果在一个类中想要执行另一个类中的方法可以使用通知
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。

PS:这里简单说一下通知中心保存的调度表。通知中心的调度表是给一些观察者指定的一些通知集。一个通知集是通知中心发出的通知的子集。每个表的入口包含:

通知观察者(必须要的)、通知名称、通知的发送者。

下图表示通知集中指定的通知的调用表入口的四种类型:

下图表示四种观察者的调度表

最后,提醒一下观察者收到通知的顺序是没有定义的。同时通知发出和观察的对象有可能是一样的。通知中心同步转发通知给观察者,就是说 postNotification: 方法直到接收并处理完通知才返回值。要想异步的发送通知,可以使用NSNotificationQueue。在多线程编程中,通知一般是在一个发出通知的那个线程中转发,但也可能是不在同一个线程中转发通知。

在对象间传递信息的标准方法是消息传递-即一个对象调用另一个对象的方法。然而,消息传递要求发送消息的对象知道消息的接收者,以及它可以响应什么 消息。这个要求对于委托消息和其它类型的消息是可以的。有些时候,我们不希望两个对象之间具有这种紧密的耦合-特别值得注意的原因是它会把本来独立的子系 统联结在一起。而且这种要求也是不切实际的,因为它需要把应用程序中很多全然不同的对象之间建立硬编码的连接。

对于不能使用标准的消息传递的场合,Cocoa提供了通告广播模型。通过通告机制,一个对象可以通知其它对象自己正在干什么。在这个意义上,通告机 制类似于委托,但是它们之间的区别是很重要的。委托和通告的关键区别在于前者是一对一的通讯路径(在向外委托任务的对象和被委托的对象之间)。而通告是潜 在的一对多的通讯方式-也就是一种广播。一个对象只能有一个委托,但可以有很多观察者,因为通告的接收者是未知的。对象不必知道那些观察者是什么对象。任何对象都可以间接地通过通告来观察一个事件,并通过调整自己的外观、行为、和状态来响应事件。通告是一种在应用程序中进行协调和聚合的强大机制。

通告机制是如何工作的?这在概念上相当直接。在进程中有一个称为通告中心的对象,充当通告的信息交换和广播中心。在应用程序的其它地方,需要知道某 个事件的对象在通告中心进行注册,让它知道当该事件发生时,自己希望得到通知。这种场景的一个例子是当一个弹出式菜单被选择时,控制器对象需要知道这个事 件,以便在用户界面上对反映这个变化。当事件发生时,处理该事件的对象向通告中心发出一个通告,然后通告中心会将它派发给所有的相关的观察者。图5-8描述了这种机制。

请注意:通告中心同步地将通告派发给它的观察者。发出通告的对象直到所有的通告被发出后,才重新获得程序的控制权。如果需要以异步的方式发送通告,必须使用通告队列(参见”通告队列”)。通告队列在对特定的通告进行延迟处理,并根据某些具体的条件将类似的通告进行组合之后,才将通告发给通告中心。

0 0
原创粉丝点击