(摘)cocoa的NSNotification通知

摘自:http://www.apple.com.cn/developer/mac/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CommunicatingWithObjects/chapter_6_section_7.html

 

通告中心同步地将通告派发给它的观察者。发出通告的对象直到所有的通告被发出后,才重新获得程序的控制权。如果需要以异步的方式发送通告,必须使用通告队列。

 

NSNotificationCenter

每个任务都有一个缺省的通告中心,您可以通过NSNotificationCenterdefaultCenter类方法来进行访问。通告中心在单任务中处理通告。如果需要在同一个机器的不同任务之间进行通讯,可以使用分布式通告中心。

通告中心同步地将通告发送给观察者。换句话说,在发出一个通告时,在所有的观察者接收和处理完成通告之前,程序的控制权不会返回给发送者。如果需要异步发送通告,可以使用通告队列,这在"通告队列"部分中进行描述。

在多线程的应用程序中,通告总是在发送的线程中传送,这个线程可能不同于观察者注册所在的线程。

NSDistributedNotificationCenter

每个任务都有一个缺省的分布式通告中心,您可以通过NSDistributedNotificationCenterdefaultCenter类方法来访问。这个分布式通告中心负责处理同一个机器的不通任务之间的通告。如果需要实现不同机器上的任务间通讯,请使用分布式对象。

发送分布式通告是一个开销昂贵的操作。通告会被发送给一个系统级别的服务器,然后再分发到注册了该分布式通告的对象所在的任务中。发送通告和通告到达另一个任务之间的延迟是很大的。事实上,如果发出的通告太多,以致于充满了服务器的队列,就可能被丢弃。

分布式通告通过任务的运行循环来分发。任务必须运行在某种“常见”模式的运行循环下,比如NSDefaultRunLoopMode模式,才能接收分布式通告。如果接收通告的任务是多线程的,则不要以通告会到达主线程作为前提。通告通常被分发到主线程的运行循环上,但是其它线程也可以接收通告。

尽管常规的通告中心允许任何对象作为通告对象(也就是通告封装的对象),分布式通告中心只支持将NSString对象作为它的通告对象。由于发出通告的对象和通告的观察者可能位于不同的任务中,通告不能包含指向任意对象的指针。因此,分布式通告中心要求通告使用字符串作为通告对象。通告的匹配就是基于这个字符串进行的,而不是基于对象指针。

通告队列

NSNotificationQueue对象(或者简单称为通告队列)的作用是充当通告中心(NSNotificationCenter的实例)的缓冲区。通告队列通常以先进先出(FIFO)的顺序维护通告。当一个通告上升到队列的前面时,队列就将它发送给通告中心,通告中心随后将它派发给所有注册为观察者的对象。

每个线程都有一个缺省的通告队列,与任务的缺省通告中心相关联。图5-9展示了这种关联。您可以创建自己的通告队列,使得每个线程和通告中心有多个队列。

聚结的通告

NSNotificationQueue类为Foundation Kit的通告机制增加了两个重要的特性:即通告的聚结和异步发送。聚结是把和刚进入队列的通告相类似的其它通告从队列中移除的过程。如果一个新的通告和已经在队列中的通告相类似,则新的通告不进入队列,而所有类似的通告(除了队列中的第一个通告以外)都被移除。然而,您不应该依赖于这个特殊的聚结行为。

您可以为enqueueNotification:postingStyle:coalesceMask:forModes:方法的第三个参数指定如下的一或多个常量,指示简化的条件:

  • NSNotificationNoCoalescing

  • NSNotificationCoalescingOnName

  • NSNotificationCoalescingOnSender

您可以对NSNotificationCoalescingOnNameNSNotificationCoalescingOnSender常量进行位或操作,指示Cocoa同时使用通告名称和通告对象进行聚结。那样的话,和刚刚进入队列的通告具有相同名称和发送者对象的所有通告都会被聚结。

异步发送通告

通过NSNotificationCenter类的postNotification:方法及其变体,您可以将通告立即发送给通告中心。但是,这个方法的调用是同步的:即在通告发送对象可以继续执行其所在线程的工作之前,必须等待通告中心将通告派发给所有的观察者并将控制权返回。但是,您也可以通过NSNotificationQueueenqueueNotification:postingStyle:enqueueNotification:postingStyle:coalesceMask:forModes:方法将通告放入队列,实现异步发送,在把通告放入队列之后,这些方法会立即将控制权返回给调用对象。

Cocoa根据排队方法中指定的发送风格和运行循环模式来清空通告队列和发送通告。模式参数指定在什么运行循环模式下清空队列。举例来说,如果您指定NSModalPanelRunLoopMode模式,则通告只有当运行循环处于该模式下才会被发送。如果当前运行循环不在该模式下,通告就需要等待,直到下次运行循环进入该模式。

向通告队列发送通告可以有三种风格:NSPostASAPNSPostWhenIdle、和NSPostNow,这些风格将在接下来的部分中进行说明。

尽快发送

NSPostASAP风格进入队列的通告会在运行循环的当前迭代完成时被发送给通告中心,如果当前运行循环模式和请求的模式相匹配的话(如果请求的模式和当前模式不同,则通告在进入请求的模式时被发出)。由于运行循环在每个迭代过程中可能进行多个OnN 模r

NSPostA_ref/doc/uid/TP40002974-CH7-DontLinkElementID_854">通过风栀和NSPo的通告会在运行循硁齓前迭代帋才下次状态布弱于运运衄当可状态e>NSDe前迭代完输伀道䎲夺通剺class包括Pan器聚结扺cla行P风栀和NSPo的通告会在运贵的擅常釾子宽午键文本有权不会的模围到丘甈本字节长度候衄弚午输fa中的,賕䀂<㈖本输f簺寸/p> 速输䮌候衄当可情况e>NSDe方掯的fa中嚄,键䖹法会珑诸221;模ChangeTheDisplayedSize运行当刚刚舗之/p> 风栀和NSPo的鑊上弚午<止输䮌候发送罓剪环外)221;模ChangeTheDisplayedSize运行嘟列中环在h4>

原因el掯的当前迭代倚告下次状态唱于运行甯明〹通前釿和制袳意SDe前迭代忔回doc/ui樽并将掾伀道耿完候厯meV可情况el并國才下次状态透通倹送诹象和通itle="Posting As Soon As PossiImen antelyref/doc/uid/TP40002974-CH7-DontLinkElementID_116">

NSPostASAP
风些风格列的通告会在运行循环的h4> 法会羚告中心㝢旆是,这个摊立即叜于老通告,code>lp>您完候 和
风些风格列的駰为通tificanter类的方法及其变体,抡忚告放衄夞上>编C忢e>NSDef们逻作䜨通告p>您庎对象希望和齓可p>您庎送告竸望任务中处牀有的观喹法-CH7-D了便确Pan制权p> <您一个通呈除了队列䚄观寙个璌风些风格列的駰对象指駰和方法及其变体,itle="Peader post_bodMySignatur