Notification Centers 通知中心

Notification Centers

通知中心

A notification center manages the sending and receiving of notifications. It notifies all observers of notifications meeting specific criteria. The notification information is encapsulated
in NSNotification objects. Client objects register themselves with the notification center as observers of specific notifications posted by other objects. When an event occurs,
an object posts an appropriate notification to the notification center. (See “Posting a Notification” for more on posting notifications.) The
notification center dispatches a message to each registered observer, passing the notification as the sole argument. It is possible for the posting object and the observing object to be the same.

Cocoa includes two types of notification centers:

  • The NSNotificationCenter class manages notifications within a single process.
  • The NSDistributedNotificationCenter class manages notifications across multiple processes on a single computer.

    一个通知中心管理着通知的发送和接收。它会通知所有满足指定规则的观察者。通知的信息被封装在NSNotification对象中。客户对象将自身注册到通知中心作为从其他对象发送来的具体通知的观察者。当一个事件发生时,对象将发布一个合适的通知到通知中心(查看 “Posting
    a Notification”
    了解更多)。通知中心分派一个消息到每一个被注册的观察者,并作为唯一的参数传递通知。存在发送者对象和观察者对象是同一个对象的可能。

    Cocoa包括两种类型的通知中心:

  • NSNotificationCenter类管理单进程内的通知。
  • NSDistributedNotificationCenter类在一台计算中通过多进程管理通知。

NSNotificationCenter

通知中心

Each process has a default notification center that you access with the NSNotificationCenter +defaultCenter class method.
This notification center handles notifications within a single process. For communication between processes on the same machine, use a distributed notification center (see “NSDistributedNotificationCenter”).

A notification center delivers notifications to observers synchronously. In other words, when posting a notification, control does not return to the poster until all observers have received and processed the notification. To send notifications
asynchronously use a notification queue, which is described in “Notification Queues.”

In a multithreaded application, notifications are always delivered in the thread in which the notification was posted, which may not be the same thread in which an observer registered itself.

每一个进程都有一个默认的通知中心,你可以使用NSNotificationCenter类的+defaultCenter类方法进行访问。这个通知中心控制着这个进程内的通知。你可以使用分布式通知中心实现不同进程间的通信 (see “NSDistributedNotificationCenter”)。

通知中心传送通知到观察者是同步的,也就是说,当通知中心发送一个通知,所有的观察者都已接收并处理了通知后控制权才会返回。要同步地发送通知,需要使用通知队列,关于通知队列的描述详见“Notification Queues.”

在一个多线程的应用里面,通知通常在发布通知的那个线程内进行传送,这个线程跟观察者注册自身的那个线程可能并不是同一个。

NSDistributedNotificationCenter

分布式通知中心

Each process has a default distributed notification center that you access with the NSDistributedNotificationCenter +defaultCenter class
method
. This distributed notification center handles notifications that can be sent between processes on a single machine. For communication between processes on different machines, use distributed objects (see Distributed Objects Programming Topics).

每一个进程都有一个默认的分布式通知中心,你可以使用NSDistributedNotificationCenter类的+defaultCenter类方法进行访问。这个通知中心控制着同一台机器上可以在不同进程间发送的通知。在不同机器的不同进程间通信,使用分布式对象。

Posting a distributed notification is an expensive operation. The notification gets sent to a systemwide server that then distributes it to all the processes that have objects registered for distributed notifications. The latency between
posting the notification and the notification’s arrival in another process is unbounded. In fact, if too many notifications are being posted and the server’s queue fills up, notifications can be dropped.

发布一个分布式通知是一个开销很大的操作。通知被发送到系统服务,然后再被系统服务分发到所有注册了分布式通知的对象的进程。发布通知与通知到达另外一个进程之间的潜在因素是不受控的。实际上,如果发布了太多的通知导致服务队列被填满,通知会被删除。

Distributed notifications are delivered via a process’s run loop. A process must be running a run loop in one of the “common” modes, such as NSDefaultRunLoopMode,
to receive a distributed notification. If the receiving process is multithreaded, do not depend on the notification arriving on the main thread. The notification is usually delivered to the main thread’s run loop, but other threads could also receive the notification.

分布式通知通过进程的运行循环进行传送,进程必须是运行在一个"common"模式下的运行循环,例如 NSDefaultRunLoopMode,去接收分布式通知。如果接收进程是多线程的,不依赖于到达主线程的通知。通知通常被传送到主线程的运行循环,但是其他的线程也可以接收这个通知。

Whereas a regular notification center allows any object to be observed, a distributed notification center is restricted to observing a string object. Because the posting object and the observer may be in different processes, notifications cannot contain
pointers to arbitrary objects. Therefore, a distributed notification center requires notifications to use a string as the notification object. Notification matching is done based on this string, rather than an object pointer.

然而,一个标准的通知中心允许被任何对象注册,分布式通知中心被限制为观察一个字符串对象。因为发布对象和观察者可能在不同的进程中,通知不能包含指向任意对象的指针。因此,一个分布式通知中心要求通知使用一个字符串作为通知对象。相比使用对象指针,通知能更好的匹配这个字符串。

Notification Queues

通知队列

NSNotificationQueue objects, or simply, notification queues, act as buffers for notification centers (instances of NSNotificationCenter).
The NSNotificationQueue class contributes two important features to the Foundation Kit’s notification mechanism: the coalescing of notifications and asynchronous
posting.

通知队列对象,或者简单说,通知队列,扮演着通知中心(NSNotificationCenter的实例)缓冲区的角色。 NSNotificationQueue 类为Foundation
Kit的通知机制贡献了两个重要的功能:聚合通知和异步发布通知。

Notification Queue Basics

通知队列基础

Using the NSNotificationCenter’s postNotification: method
and its variants, you can post a notification to a notification center. However, the invocation of the method is synchronous: before the posting object can resume its thread of execution, it must wait until the notification center dispatches the notification
to all observers and returns. A notification queue, on the other hand, maintains notifications (instances of NSNotification) generally in a First In First Out
(FIFO) order. When a notification rises to the front of the queue, the queue posts it to the notification center, which in turn dispatches the notification to all objects registered as observers.

使用NSNotificationCenter类的postNotification:方法和他的变量,你可以发送一个通知到通知中心,然而,这个方法的调用是同步的:在发布对象可以重新执行该线程前,它必须等待通知中心将通知分发到了所有已注册的对象并返回。从另一个方面来说,通知队列保持通知(NSNotification的实例)通常是先进先出的顺序。当一个通知被提升到队列前面,队列就将它发布到通知中心,这样轮流将通知分发到所有被注册为该通知观察者的对象。

Every thread has a default notification queue, which is associated with the default notification center for the process. You can createyour own notification queues and have multiple queues per center and thread.

每一个线程都有一个默认的通知队列跟进程默认的通知中心关联在一起,你可以创建自己的通知队列,每一个通知中心和线程可以拥有多个队列。

Posting Notifications Asynchronously

异步的发送通知

With NSNotificationQueue’s enqueueNotification:postingStyle: and enqueueNotification:postingStyle:coalesceMask:forModes: methods,
you can post a notification asynchronously to the current thread by putting it in a queue. These methods immediately return to the invoking object after putting the notification in the queue.

使用NSNotificationQueueenqueueNotification:postingStyle: 和enqueueNotification:postingStyle:coalesceMask:forModes:方法,你可以将通知放进队列异步地发布到当前线程,这些方法把通知放入队列后立即返回到调用对象。

Note: When the thread where a notification is enqueued terminates before the notification queue posts the notification to its notification center, the notification is not posted. See “Delivering
Notifications To Particular Threads”
 to learn how to post a notification to a different thread.

线程在通知队列发布通知到它的通知中心前结束,这个通知将不会发布。查看 “Delivering Notifications To Particular Threads” 学习如何发送通知到不同的线程。

The notification queue is emptied and its notifications posted based on the posting style and run loop mode specified in the enqueuing method. The mode argument specifies the run loop mode in which the queue will be emptied.
For example, if you specify NSModalPanelRunLoopMode, the notifications will be posted only when the run loop is in this mode. If the run loop is not currently in this mode,
the notifications wait until the next time that mode is entered. See “Run Loop Modes” in Threading
Programming Guide
 for more information.

通知队列被置空,它的通知发布基于发布格式和在队列方法中规定的运行循环模式。模式参数指定了将会被置空的那个队列所在的线程的运行循环模式。例如,如果你指定NSModalPanelRunLoopMode,通知就只会在运行循环处于该模式时被发布。如果运行循环当前不是处于该模式,通知就需要等到运行循环下一次进入该模式才能被发布。查看Threading
Programming Guide
中的“Run Loop Modes”
了解更多信息。

Posting to a notification queue can occur in one of three different styles: NSPostASAPNSPostWhenIdle,
and NSPostNow. These styles are described in the following sections.

通知队列的发布可以选择以下三种不同的格式之一:NSPostASAPNSPostWhenIdle,
和 NSPostNow.这些格式在接下来的段落中进行描述。

Posting As Soon As Possible

尽快发布

Any notification queued with the NSPostASAP style is posted to the notification center
when the current iteration of the run loop completes, assuming the current run loop mode matches the requested mode. (If the requested and current modes are different, the notification is posted when the requested mode is entered.) Because the run loop can
make multiple callouts during each iteration, the notification may or may not get delivered as soon as the current callout exits and control returns to the run loop. Other callouts may take place first, such as a timer or source firing or other asynchronous
notifications being delivered.

假设当前的运行循环与要求的运行循环是匹配的,那么任何NSPostASAP格式的通知会在运行循环当前迭代完成时被发布到统治中心(如果要求的运行循环与当面运行循环不同,通知会在运行循环下一次进入该模式时被发布)。因为运行循环在每一次迭代中可以处理多个callout,通知可能不会在当前callout退出后立即传送并将控制返回到运行循环。其他的callout可能被优先处理,例如时间或者资源占用,或者其他异步通知正在传送。

You typically use the NSPostASAP posting style for an expensive resource, such as the
display server. When many clients draw on the window buffer during a callout from the run loop, it is expensive to flush the buffer to the display server after every draw operation. In this situation, each draw... method
enqueues some notification such as “FlushTheServer” with coalescing on name and object specified and with a posting style of NSPostASAP. As a result, only one of those notifications
is dispatched at the end of the run loop and the window buffer is flushed only once.

你通常为一个开销大的资源使用NSPostASAP发布格式,例如显示服务,当很多客户端从运行循环中在缓存在callout中的窗口上绘制时,每一次绘制操作后刷新显示服务缓冲区的开销是很大的。在这种条件下,每一个绘制方法都产生一些通知排队,形如“FlushTheServer”的根据名称聚合的通知和指定的对象,以及NSPostASAP的发布格式。最终,这些通知有且只有一个在运行循环结束时被分发,而且窗口缓冲区也只刷新一次。

Posting When Idle

空闲时发布

A notification queued with the NSPostWhenIdle style is posted only when the run loop is in a wait
state. In this state, there’s nothing in the run loop’s input channels, be it timers or other asynchronous events. A typical example of queuing with the NSPostWhenIdle style
occurs when the user types text, and the program displays the size of the text in bytes somewhere. It would be very expensive (and not very useful) to update the text field size after each character the user types, especially if the user types quickly. In
this case, the program queues a notification, such as “ChangeTheDisplayedSize,” with coalescing turned on and a posting style of NSPostWhenIdle after
each character typed. When the user stops typing, the single “ChangeTheDisplayedSize” notification in the queue (due to coalescing) is posted when the run loop enters its wait state and the display is updated. Note that a run loop that is about to exit (which
occurs when all of the input channels have expired) is not in a wait state and thus will not post a notification.

Posting Immediately

立即发布

A notification queued with NSPostNow is posted immediately after coalescing to the notification
center. You queue a notification with NSPostNow (or post one with postNotification:)
when you do not require asynchronous calling behavior. For many programming situations, synchronous behavior is not only allowable but desirable: You want the notification center to return after dispatching so you can be sure that observing objects have received
and processed the notification. Of course, you should use enqueueNotification... with NSPostNow rather
than use postNotification: when there are similar notifications in the queue that you want to remove through coalescing.

Coalescing Notifications

聚合通知

In some situations, you may want to post a notification if a given event occurs at least once, but you want to post no more than one notification even if the event occurs multiple times. For example, in an application that receives data in discrete packets,
upon receipt of a packet you may wish to post a notification to signify that the data needs to be processed. If multiple packets arrive within a given time period, however, you do not want to post multiple notifications. Moreover, the object that posts these
notifications may not have any way of knowing whether more packets are coming or not, whether the posting method is called in a loop or not.

在某些情况下,你可能希望在一个给定的事件发生时至少发送一次通知,但是你希望发送不止一条通知,即使这个事件多次发生。例如,在应用中接收分包传输的数据,根据接收到的数据包你可能希望发布一个通知表示数据需要被执行。如果多个数据包在给定的时间段内到达,你不希望发布多个通知。但是情况不止是这样,发送通知的对象可能并没有任何方式知道是否还有更多的数据包发送过来,发布方法是否在一个循环中调用。

In some situations it may be possible to simply set a Boolean flag (whether an instance variable of an object or a global variable) to denote that an event has occurred and to suppress posting of further notifications until
the flag is cleared. If this is not possible, however, in this situation you cannot directly use NSNotificationCenter since its behavior is synchronous—notifications are posted
before returning, thus there is no opportunity for "ignoring” duplicate notifications; moreover, an NSNotificationCenterinstance has no way of knowing whether more notifications
are coming or not.

在某些情况下,它可能只是简单的去设置一个布尔标识(不管是一个对象的实例变量还是全局变量)用来表示一个事件已经发生了,在这个标识被清空前需要抑制更进一步的发布通知。如果不能这样做,那么在这种情况下你就会因为它的行为是同步的而不能直接使用NSNotificationCenter——通知在返回前被发布,这样就没有机会“忽略”重复的通知,而且,统治中心实例也没有办法知道是否有更多的通知到来。

Rather than posting a notification to a notification center, therefore, you can add the notification to an NSNotificationQueueinstance specifying
an appropriate option for coalescing. Coalescing is a process that removes from a queue notifications that are similar in some way to a notification that was queued earlier. You indicate the criteria for similarity by specifying
one or more of the following constants in the third argument of the enqueueNotification:postingStyle:coalesceMask:forModes: method.

与其发布一个通知到统治中心,倒不如添加通知到一个NSNotificationQueue实例并制定合适的条件使其聚合。聚合是将较早在队列里面排队的并在某些方面相似的通知移除的过程,你可以通过指定一个或者多个限制条件作为以下方法的第三个参数,来标示相似的标准。

NSNotificationNoCoalescing
Do not coalesce notifications in the queue.

不在队列里面聚合通知

NSNotificationCoalescingOnName
Coalesce notifications with the same name.

以相同的名称聚合通知

NSNotificationCoalescingOnSender
Coalesce notifications with the same object.

以相同的对象聚合通知

You can perform a bitwise-OR operation with the NSNotificationCoalescingOnName and NSNotificationCoalescingOnSenderconstants
to specify coalescing using both the notification name and notification object. The following example illustrates how you might use a queue to ensure that, within a given event loop cycle, all notifications named MyNotificationName are
coalesced into a single notification.

你可以使用按位或操作使用NSNotificationCoalescingOnNameNSNotificationCoalescingOnSender来指定同时按照名称和对象进行聚合。下面的例子说明了如何使用一个队列去验证这个规则,例子中已经给定了一个事件循环,所有名称为MyNotificationName的通知都被聚合成了一条单独的通知。

// MyNotificationName defined globally
NSString *MyNotificationName = @"MyNotification";

id object = <#The object associated with the notification#>;
NSNotification *myNotification =
        [NSNotification notificationWithName:MyNotificationName object:object]
[[NSNotificationQueue defaultQueue]
        enqueueNotification:myNotification
        postingStyle:NSPostWhenIdle
        coalesceMask:NSNotificationCoalescingOnName

        forModes:nil];

Registering for a Notification

注册通知

You can register for notifications from within your own application or other applications. See “Registering for Local Notifications”for
the former and “Registering for Distributed Notifications” for the latter. To unregister for a notification, which must be done when your object
is deallocated, see “Unregistering an Observer.”

你可以从一个应用内注册一个通知,也可以从其他应用注册通知。可以先查看注册本地通知的相关内容,再查看注册分布式通知的相关内容。当注销一个通知时,当对象被销毁时通知必须完成。

Registering for Local Notifications

注册本地通知

You register an object to receive a notification by invoking the notification center method addObserver:selector:name:object:, specifying the observer,
the message the notification center should send to the observer, the name of the notification it wants to receive, and about which object. You don’t need to specify both the name and the object. If you specify only an object,
the observer will receive all notifications containing that object. If you specify only a notification name, the observer will receive that notification every time it’s posted, regardless of the object associated with it.

你可以调用通知中心的addObserver:selector:name:object:方法去注册一个对象接受通知消息,定制观察者,通知中心应该发送给观察者的消息,希望接收的通知名字,和接收哪一个对象的通知。你不需要详细说明通知名字和发送通知的对象,如果你只指定了发送通知的对象,观察者将会接收所有那个对象的通知。如果你只指定了通知名称,观察者将会接收这个通知每次发送的消息,而且不管这个通知是否与对象相关联。

It is possible for an observer to register to receive more than one message for the same notification. In such a case, the observer will receive all messages it is registered to receive for the notification, but the order in which it receives them cannot
be determined.

存在一种可能就是,一个观察者注册为接收同一个通知的不止一条消息。在这种情况下,这个观察者将会接收它注册的这个通知发送的所有消息,但是接收这些消息的顺序是无法确定的。

If you later decide an observer no longer needs to receive notifications (for example, if the observer is being deallocated), you can remove the observer from the notification center’s list of observers with the methods removeObserver: or removeObserver:name:object:.

如果你稍后希望观察者不再接收通知(例如,观察者对象被销毁),你可以使用removeObserver:或者removeObserver:name:object:方法从通知中心列表中移除这个观察者。

Normally, you register objects with the process’s default notification center. You obtain the default object using the defaultCenter class  method.

通常,你使用进程默认的通知中心注册观察者对象。你可以使用defaultCenter 类方法获得默认的通知中心对象。

As an example of using the notification center to receive notifications, suppose you want to perform an operation any time a window becomes main (for example, if you’re implementing a controller for an inspector panel).
You would register your client object as an observer as shown in the following example:

下面是一个使用通知中心接收通知的例子,假设你想在某个时间执行一个操作将窗口变为主窗口,你可以按照如下代码所示的方式将一个客户端对象作为一个观察者对象注册到通知中心。

[[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(aWindowBecameMain:)
    name:NSWindowDidBecomeMainNotification object:nil];

By passing nil as the object to observe, the client object (self)
is notified when any object posts a NSWindowDidBecomeMainNotification notification.

传递一个nil 作为对象给观察者,那么任何对象发布的NSWindowDidBecomeMainNotification通知都会通知给这个观察者。

When window becomes main, it posts an NSWindowDidBecomeMainNotification to the notification center. The notification center notifies all observers who are
interested in the notification by invoking the method they specified in the selector argument of addObserver:selector:name:object:.
In the case of our example observer, the selector is aWindowBecameMain:. The aWindowBecameMain: method
might have the following implementation:

当窗口变为主窗口,它发布一个NSWindowDidBecomeMainNotification通知到通知中心,通知中心通知所有对这个通知感兴趣的观察者,观察者是调用addObserver:selector:name:object:方法并指定相关参数来告诉通知中心自己对那些通知感兴趣的。在我们例子中的这种情况,接收到通知后,观察者响应的方法是aWindowBecameMain:,这个方法可能的实现方式如下所示:

- (void)aWindowBecameMain:(NSNotification *)notification {

    NSWindow *theWindow = [notification object];
    MyDocument = (MyDocument *)[[theWindow windowController] document];

    // Retrieve information about the document and update the panel.
}

The NSWindow objects don’t need to know anything about your inspector panel.

Registering for Distributed Notifications

An object registers itself to receive a notification by sending the addObserver:selector:name:object:suspensionBehavior:method to an NSDistributedNotificationCenter object,
specifying the message the notification should send, the name of the notification it wants to receive, the identifying string to match (the object argument), and the behavior to follow if notification delivery is suspended.

Because the posting object and the observer may be in different processes, notifications can’t contain pointers to arbitrary objects. Therefore, the NSDistributedNotificationCenter class
requires notifications to use an NSString object as the objectargument. Notification matching is done based on this string, rather than an object pointer. You should
check the documentation of the object posting the notification to see what it uses as its identifying string.

When a process is no longer interested in receiving notifications immediately, it may suspend notification delivery. This is often done when the application is hidden, or is put into the background. (The NSApplication object
automatically suspends delivery when the application is not active.) The suspensionBehavior argument in the addObserver method identifies how arriving notifications
should be handled while delivery is suspended. There are four different types of suspension behavior, each useful in different circumstances.


Suspension Behavior


Description


NSNotificationSuspensionBehaviorDrop


The server does not queue any notifications with this name and object until it receives the setSuspended:NO message.


NSNotificationSuspensionBehaviorCoalesce


The server queues only the last notification of the specified name and object; earlier notifications are dropped. In cover methods for which suspension behavior is not an explicit argument, NSNotificationSuspensionBehaviorCoalesce is
the default.


NSNotificationSuspensionBehaviorHold


The server holds all matching notifications until the queue has been filled (queue size determined by the server) at which point the server may flush queued notifications.


NSNotificationSuspensionBehaviorDeliverImmediately


The server delivers notifications matching this registration irrespective of whether it has received the setSuspended:YESmessage. When a notification with this suspension
behavior is matched, it has the effect of first flushing any queued notifications. The effect is as if the server received setSuspended:NO while the application is suspended,
followed by the notification in question being delivered, followed by a transition back to the previous suspended or unsuspended state.

You suspend notifications by sending setSuspended:YES to the distributed notification center. While notifications are suspended, the notification server
handles notifications destined for the process that suspended notification delivery according to the suspension behavior specified by the observers when they registered to receive notifications. When the process resumes notification delivery, all queued notifications
are delivered immediately. In applications using Application Kit, the NSApplicationobject automatically suspends notification delivery when the application is not active.

Note that a notification destined for an observer that registered with NSNotificationSuspensionBehaviorDeliverImmediately, automatically flushes the
queue as it is delivered, causing all queued notifications to be delivered at that time as well.

The suspended state can be overridden by the poster of a notification. If the notification is urgent, such as a warning of a server being shut down, the poster can force the notification to be delivered immediately to all observers
by posting the notification with the NSDistributedNotificationCenter postNotificationName:object:userInfo:deliverImmediately: method with the deliverImmediately argument YES.

Unregistering an Observer

Before an object that is observing notifications is deallocated, it must tell the notification center to stop sending it notifications. Otherwise, the next notification gets sent to a nonexistent object and the program crashes.
You can send the following message to completely remove an object as an observer of local notifications, regardless of how many objects and notifications for which it registered itself:

在一个被注册到通知中心的对象被销毁前,它必须告诉通知中心停止向其发送通知。否则,下一个通知将会被发送给一个不存在的对象并导致程序崩溃。无论这个对象注册到了多少个通知中心,你都可以发送下面这条消息将它从本地通知中完全移除。

[[NSNotificationCenter defaultCenter] removeObserver:self];

For observers of distributed notifications send:

移除分布式通知的观察者发送:

[[NSDistributedNotificationCenter defaultCenter] removeObserver:self];

Use the more specific removeObserver... methods that specify the notification name and observed object to selectively unregister an object
for particular notifications.

使用 removeObserver… 方法的更多特性去指定通知名称和从一个特定的通知中注销观察者对象。

Posting a Notification

You can post notifications within your own application or make them available to other applications. See “Posting Local
Notifications”
 for the former and “Posting Distributed Notifications” for the latter.

你可以在你自己的应用内发布通知,也可以使你的通知在其他应用可见,前者阅读“Posting Local Notifications”,后者阅读“Posting
Distributed Notifications”
 。

Posting Local Notifications

You can create a notification object with notificationWithName:object: or notificationWithName:object:userInfo:.
You then post the notification object to a notification center using the postNotification: instance method. NSNotification objects
are immutable, so once created, they cannot be modified.

你可以使用notificationWithName:object:
或or notificationWithName:object:userInfo:方法创建通知。然后使用实例方法将通知对象发布到统治中心。通知对象是不可变的,所以一旦创建就不可以再修改。

However, you normally don’t create your own notifications directly. The methods postNotificationName:object: and postNotificationName:object:userInfo: of
the NSNotificationCenter class allow you to conveniently post a notification without creating it first.

然而,你通常不会直接创建你自己的通知。通知中心的postNotificationName:object:和postNotificationName:object:userInfo: 方法允许你方便的发送通知而不需要先创建它。

In each case, you usually post the notification to the process’s default notification center. You obtain the default object using the defaultCenter class
method
.

无论哪种情况,你通常将通知发布到进程默认的统治中心。你可以使用defaultCenter类方法获得这个通知中心对象。

As an example of using the notification center to post a notification, consider the example from “Registering for Local
Notifications.”
 You have a program that can perform a number of conversions on text (for instance, RTF to ASCII). The conversions are handled by a class of objects (Converter)
that can be added or removed during program execution. Your program may have other objects that want to be notified when converters are added or removed, but the Converter objects
do not need to know who these objects are or what they do. You thus declare two notifications, "ConverterAdded" and "ConverterRemoved",
which you post when the given event occurs.

作为使用通知中心发布通知的一个例子,思考“Registering for Local Notifications.”这个例子,你有一个程序可以对文本执行一些转换(例如,将RTF转换成ASCII),这个转换由可以在程序执行中添加或移除的对象的类管理,你的程序可能还有其他的对象希望当转换被添加或移除时收到通知,但是这个转换对象不用知道哪些需要收到通知的类和他们可以做什么。因此,你只需要声明两个通知,"ConverterAdded” 和 "ConverterRemoved",在添加或删除事件发生时发布。

When a user installs or removes a converter, it sends one of the following messages to the notification center:

当用户安装或者移除转换器时,它会发送下面的消息:

[[NSNotificationCenter defaultCenter]
    postNotificationName:@"ConverterAdded" object:self];

or

[[NSNotificationCenter defaultCenter]
    postNotificationName:@"ConverterRemoved" object:self];

The notification center then identifies which objects (if any) are interested in these notifications and notifies them.

通知中心会识别哪些对象对这些通知感兴趣并通知他们。

If there are other objects of interest to the observer (besides the notification name and observed object), place them in the notification’s optional dictionary or use postNotificationName:object:userInfo:.

这段是什么意思?userInfo到底干嘛用

Posting Distributed Notifications

Posting distributed notifications is much the same as for posting local notifications. You can create an NSNotification object
manually and post with postNotification: or use one of the NSDistributedNotificationCenter convenience
methods. The only differences are that the notification object must be a string object and the optional user-info dictionary can contain only property list objects, such as NSString and NSNumber.

An observer of a given notification may be in a suspended state and not processing notifications immediately. If an object posting a notification wants to ensure that all observers receive the notification immediately (for
example, if the notification is a warning that a server is about to shut down), it can invoke postNotificationName:object:userInfo:deliverImmediately: with deliverImmediately:YES.
The notification center delivers the notification as if the observers had registered with NSNotificationSuspensionBehaviorDeliverImmediately (further described in “Registering
for Distributed Notifications”
). Delivery is not guaranteed, however. For example, the process receiving the notifications may be too busy to process and accept queued notifications. In this case, the notification is dropped.

Delivering Notifications To Particular Threads

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.

One way to redirect notifications is to use a custom notification queue (not an NSNotificationQueue object) to hold any notifications that are received
on incorrect threads and then process them on the correct thread. This technique works as follows. You register for a notification normally. When a notification arrives, you test whether the current thread is the thread that should handle the notification.
If it is the wrong thread, you store the notification in a queue and then send a signal to the correct thread, indicating that a notification needs processing. The other thread receives the signal, removes the notification from the queue, and processes the
notification.

To implement this technique, your observer object needs to have instance variables for the following values: a mutable array to hold the notifications, a communication port for signaling the correct
thread (a Mach port), a lock to prevent multithreading conflicts with the notification array, and a value that identifies the correct thread (an NSThread object). You also
need methods to setup the variables, to process the notifications, and to receive the Mach messages. Here are the necessary definitions to add to the class of your observer object.

@interface MyThreadedClass: NSObject
/* Threaded notification support. */
@property NSMutableArray *notifications;
@property NSThread *notificationThread;
@property NSLock *notificationLock;
@property NSMachPort *notificationPort;

- (void) setUpThreadingSupport;
- (void) handleMachMessage:(void *)msg;
- (void) processNotification:(NSNotification *)notification;
@end

Before registering for any notifications, you need to initialize the properties. The following method initializes the queue and lock objects, keeps a reference to the current thread object, and creates
a Mach communication port, which it adds to the current thread’s run loop.

- (void) setUpThreadingSupport {
    if (self.notifications) {
        return;
    }
    self.notifications      = [[NSMutableArray alloc] init];
    self.notificationLock   = [[NSLock alloc] init];
    self.notificationThread = [NSThread currentThread];

    self.notificationPort = [[NSMachPort alloc] init];
    [self.notificationPort setDelegate:self];
    [[NSRunLoop currentRunLoop] addPort:self.notificationPort
            forMode:(NSString __bridge *)kCFRunLoopCommonModes];
}

After this method runs, any messages sent to notificationPort are received in the run loop of the thread that first ran this method. If the receiving
thread’s run loop is not running when the Mach message arrives, the kernel holds on to the message until the next time the run loop is entered. The receiving thread’s run loop sends the incoming messages to the handleMachMessage:method
of the port’s delegate.

In this implementation, no information is contained in the messages sent to notificationPort. Instead, the information passed between threads is contained
in the notification array. When a Mach message arrives, the handleMachMessage: method ignores the contents of the message and just checks the  notifications array
for any notifications that need processing. The notifications are removed from the array and forwarded to the real notification processing method. Because port messages may get dropped if too many are sent simultaneously, the handleMachMessage: method iterates over
the array until it is empty. The method must acquire a lock when accessing the notification array to prevent conflicts between one thread adding notifications and another removing notifications from the array.

- (void) handleMachMessage:(void *)msg {

    [self.notificationLock lock];

    while ([self.notifications count]) {
        NSNotification *notification = [self.notifications objectAtIndex:0];
        [self.notifications removeObjectAtIndex:0];
        [self.notificationLock unlock];
        [self processNotification:notification];
        [self.notificationLock lock];
    };

    [self.notificationLock unlock];
}

When a notification is delivered to your object, the method that receives the notification must identify whether it is running in the correct thread or not. If it is the correct thread, the notification is processed normally. If it
is the wrong thread, the notification is added to the queue and the notification port signaled.

- (void)processNotification:(NSNotification *)notification {

    if ([NSThread currentThread] != notificationThread) {
        // Forward the notification to the correct thread.
        [self.notificationLock lock];
        [self.notifications addObject:notification];
        [self.notificationLock unlock];
        [self.notificationPort sendBeforeDate:[NSDate date]
                components:nil
                from:nil
                reserved:0];
    }
    else {
        // Process the notification here;
    }
}

Finally, to register for a notification that you want delivered on the current thread, regardless of the thread in which it may be posted, you must initialize your object’s notification properties by invoking setUpThreadingSupport and
then register for the notification normally, specifying the special notification processing method as the selector.

[self setupThreadingSupport];
[[NSNotificationCenter defaultCenter]
        addObserver:self
        selector:@selector(processNotification:)
        name:@"NotificationName"
        object:nil];

This implementation is limited in several aspects. First, all threaded notifications processed by this object must pass through the same method (processNotification:).
Second, each object must provide its own implementation and communication port. A better, but more complex, implementation would generalize the behavior into either a subclass of NSNotificationCenter or
a separate class that would have one notification queue for each thread and be able to deliver notifications to multiple observer objects and methods.

Document Revision History

This table describes the changes to Notification Programming Topics.

Date Notes
2009-08-18 Added links to key Cocoa definitions.
2009-05-24 Removed obsolete references to Java classes.
2007-05-03 Noted that distributed notification centers deliver notifications on the main thread.
2007-01-08 Corrected minor typographical errors.
2006-11-07 Enhanced description of coalescing notifications.
2006-04-04 Clarified on which thread an enqueued notification is posted. Changed title from "Notifications."
 
Specified that notifications are posted on the same thread where they are enqueued in “Posting Notifications Asynchronously.”

 
Indicated that notifications are used throughout the Cocoa frameworks and pointed out where such notifications are described in “Notifications.”

2002-11-12
Revision history was added to existing topic. It will be used to record changes to the content of the topic.

时间: 2024-10-01 05:24:41

Notification Centers 通知中心的相关文章

IOS8 通知中心(Notification Center)新特性

本文转载至 http://blog.csdn.net/jinkaiouyang/article/details/30029441 ios手机apple通知中心notificationCenter   苹果keynote展示push通知的一些优化,特别的允许用户能够直接在push上进行交互,这么牛逼的功能,当然第一时间研究. 下面看看具体的产品细节和技术实现:   产品细节: 以下都是使用本地push测试的:(离线push效果一样) 1.状态栏.锁屏状态下和通知中心中的效果如下:(这里最多只能设置

iOS之NSNotificationCenter通知中心使用事项

其实这里的通知和之前说到的KVO功能很想,也是用于监听操作的,但是和KVO不同的是,KVO只用来监听属性值的变化,这个发送监听的操作是系统控制的,我们控制不了,我们只能控制监听操作,类似于Android中系统发送的广播,我们只能接受.但是通知就不一样了,他的监听发送也是又我们自己控制,我们可以在任何地方任何时机发送一个通知,类似于Android中开发者自己发送的广播.从这一点看来,通知的使用场景更为广泛了. 下面就来看一下例子: 还是护士和小孩的那个例子 Children.h [objc] vi

通知中心 - NSNotificationCenter

---恢复内容开始--- NS_ASSUME_NONNULL_BEGIN /**************** Notifications ****************/ // 通知,被发送,被接受. @interface NSNotification : NSObject <NSCopying, NSCoding> 通知的名字 @property (readonly, copy) NSString *name; 具体某一个对象. @property (nullable, readonly,

第二十六篇:通知中心 NSNotificationCenter

1.通知中心(NSNotificationCenter) ?每一个应用程序都有一个通知中心(NSNotificationCenter)实例,专门负责协助不同对象之间的消息通信 ?任何一个对象都可以向通知中心发布通知(NSNotification),描述自己在做什么.其他感兴趣的对象(Observer)可以申请在某个特定通知发布时(或在某个特定的对象发布通知时)收到这个通知 2.通知(NSNotification) >一个完整的通知一般包含3个属性: - (NSString*)name; // 通

通知中心(NSNotificationCenter)

•通知机制 •掌握 •通知的发布 • •通知的监听 • •通知的移除 •通知中心(NSNotificationCenter) •每一个应用程序都有一个通知中心(NSNotificationCenter)实例,专门负责协助不同对象之间的消息通信 •任何一个对象都可以向通知中心发布通知(NSNotification),描述自己在做什么.其他感兴趣的对象(Observer)可以申请在某个特定通知发布时(或在某个特定的对象发布通知时)收到这个通知 •通知(NSNotification) •一个完整的通知

iOS通知中心 NSNotificationCenter详解

NSNotificationCenter的适用场景,原理机制,使用步骤等. 通知中心的使用顺序:先确保注册了观察者,因为发送通知是一瞬间的事,如果没有注册观察者,发送通知后再注册是不会收到的. 总结:通知只会发送给当前监听着的对象. 代码 //注册通知  在关心该通知的页面注册监听 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tongzhi:) name:@"tongzhi" obj

IOS中通知中心NSNotificationCenter应用总结

一.了解几个相关的类 1.NSNotification 这个类可以理解为一个消息对象,其中有三个成员变量. 这个成员变量是这个消息对象的唯一标识,用于辨别消息对象. @property (readonly, copy) NSString *name; 这个成员变量定义一个对象,可以理解为针对某一个对象的消息. @property (readonly, retain) id object; 这个成员变量是一个字典,可以用其来进行传值. @property (readonly, copy) NSDi

iOS 通知中心

原文地址 : http://www.jianshu.com/p/1208724e1915 iOS 提供了一种 "同步的" 消息通知机制NSNotificationCenter,观察者只要向消息中心注册, 即可接受其他对象发送来的消息,消息发送者和消息接受者两者可以互相一无所知,完全解耦.消息机制常常用于在向服务器端请求数据或者提交数据的场景,在和服务器端成功交互后,需要处理服务器端返回的数据,或发送响应消息等,就需要用到消息机制 一.通知相关的类 NSNotification 这个类可

iOS 通知中心快速回复

iOS8拥有了全新的通知中心,有全新的通知机制.当屏幕顶部收到推送时只需要往下拉,就能看到快速操作界面,并不需要进入该应用才能操作.在锁屏界面,对于推送项目也可以快速处理.基本上就是让用户尽量在不离开当前页面的前提下处理推送信息,再次提高处理效率. 能够进行直接互动的短信.邮件.日历.提醒,第三方应用,可以让你不用进入程序就能进行快捷操作,并专注于手中正在做的事情,用户可以做如下操作: 在通知横幅快速回复信息,不用进入短信程序: 可直接拒绝或接受邮件邀请: 可对提醒进行标记为完成或推迟: 当第三