你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS 通知機制 Notifications (三)

iOS 通知機制 Notifications (三)

編輯:IOS開發綜合

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

發布本地通知

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: 或者 notificationWithName:object:userInfo: 創建一個通知。然後你用postNotification:實例方法發布通知到通知中心。NSNotification 是不可變對象,所以一旦創建,不可更改。


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.

當然,你通常不需要直接創建自己的通知。NSNotificationCenterpostNotificationName: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:.

如果有其他觀察者感興趣的對象,可以把他們放在通知可選的字典裡,或者使用 postNotificationName:object:userInfo:

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.

一種重新發布通知的方法是使用自定義的通知隊列(注意不是NSNotificationQueue對象)去保存在不正確線程上收到的通知,然後在正確的線程上處理他們。這個技術是這樣的。你正常注冊一個通知。當通知到達時,你測試一下當前的線程是否應該處理通知。如果是錯誤的線程,你保持通知到隊列。然後發送一個信號到正確的線程,告訴它一個通知需要處理。另外一個線程收到信號,從隊列中移除通知,然後處理通知。

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.

為了實現這個技術,你的觀察者對象需要以下值的實例變量:一個保存通知的可變數組,一個通知正確線程的通信端口(a Mach port),一個防止通知數組內多線程處理沖突的鎖,一個標示正確線程(一個NSThread 對象)的值。你也需要方法去設置變量,去處理通知,去接收 Mach消息。下面是要添加到你觀察者對象中的必要的定義。

@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.

在注冊通知之前,你需要初始化這些屬性,下面的方法初始化了隊列和鎖對象,保持了一個對當前線程對象的引用,以及創建了一個Mach通信端口,它將被添加到當前線程的 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.

在這個方法運行之後,任何發送到notificationPort的消息將會在首先運行這個方法的線程的run loop中被收到。如果Mach 消息到達時,接收者線程的run loop沒有運行,內核被保持這個消息直到下次 run loop進入。接收者線程的run loop 發送未到達的消息到 端口代理的 handleMachMessage:方法。

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.


在這個實現中,發送到notificationPort的消息沒有包含任何信息。 相反,通知數組包含線程間傳遞的信息。當Mach信息到達時,handleMachMessage:方法忽略了消息的內容,只是檢查通知數組中需要處理的通知。通知從數組中移除,然後傳到真正處理通知的方法中。因為如果同時發送太多端口信息,信息可能會丟失。 handleMachMessage:方法會遍歷數組,直到它為空。當訪問通知數組時必須獲取一個鎖,以防止一個線程添加通知而另一個線程把通知從數組移除。
- (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.

這個實現在某些方面。首先,對象處理的所有線程的通知必須通過相同的方法(processNotification:)傳遞。第二,每一個對象都必須提供自己的實現和通信端口。一個更好,但是也更復雜的實現是。。。。有空補上,這段話有點復雜



  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved