Foundation框架含有一個(gè) API 集合——支持通知類茸俭,這些類提供了功能強(qiáng)大的事件驅(qū)動(dòng)編程機(jī)制吊履。
<h3 id="notify">通知</h3>
通知是指封裝起來的事件信息。它可以發(fā)送給一個(gè)或多個(gè)觀察對(duì)象调鬓,以回應(yīng)應(yīng)用程序中出現(xiàn)的事件艇炎。通知結(jié)構(gòu)效仿了廣播模型,因此能夠?qū)⒔邮帐录膶?duì)象與發(fā)送事件的對(duì)象解耦腾窝。使用通知支持類可以創(chuàng)建和傳遞通知缀踪、發(fā)送和接收通知,以及通過隊(duì)列以異步方式傳遞通知虹脯。使用 NSNotification 類可以封裝由通知對(duì)象發(fā)送的信息驴娃。其中,含有唯一名稱循集、被傳遞的對(duì)象和補(bǔ)充信息的目錄(可選)唇敞。
// 創(chuàng)建簡(jiǎn)單問候通知ApplicationDidHandleGreetingNotification
NSString * aName = @"ApplicationDidHandleGreetingNotification";
NSString * anObject = @"Hello World !";
NSNotification * notify = [NSNotification notificationWithName:aName
object:anObject];
// 發(fā)送通知
NSNotificationCenter * ncenter = [NSNotificationCenter defaultCenter];
[ncenter postNotification: notify];
// 創(chuàng)建并發(fā)送通知
[ncenter postNotificationName:aName
object:anObject];
// 注冊(cè)觀察者
Greeter *handler = [Greeter new];
[ncenter addObserver: handler
selector:@selector(handlerGreeting:)
name:aName
object:nil];
// 注銷已注冊(cè)的觀察者
[ncenter removeObserver: handler];
// 或者更加細(xì)膩的操作
[ncenter removeObserver: handler
name:aName
object:nil];
創(chuàng)建簡(jiǎn)單問候通知ApplicationDidHandleGreetingNotification,你可能好奇為什么這個(gè)通知的名稱這么長(zhǎng)咒彤?因?yàn)樘O果公司提出了一些命名通知的指導(dǎo)原則疆柔,這些原則旨在方便創(chuàng)建帶自我描述的、具有唯一性的通知名稱:
- 相關(guān)類的名稱
- 單詞 Did 或 Will
- 實(shí)現(xiàn)唯一性的名稱成分
- 單詞 Notification
<h3 id="notificationclass">了解幾個(gè)相關(guān)類</h3>
NSNotification 這個(gè)類可以理解為一個(gè)消息對(duì)象镶柱,其中有三個(gè)成員變量旷档。
// 這個(gè)成員變量是這個(gè)消息對(duì)象的唯一標(biāo)識(shí),用于辨別消息對(duì)象
@property (readonly, copy) NSString *name;
// 這個(gè)成員變量定義一個(gè)對(duì)象歇拆,可以理解為針對(duì)某一個(gè)對(duì)象的消息
@property (nullable, readonly, retain) id object;
// 這個(gè)成員變量是一個(gè)字典鞋屈,可以用其來進(jìn)行傳值
@property (nullable, readonly, copy) NSDictionary *userInfo;
// 初始化方法(官方文檔有明確的說明,不可以使用init進(jìn)行初始化)
- (instancetype)initWithName:(NSString *)name
object:(nullable id)object
userInfo:(nullable NSDictionary *)userInfo
+ (instancetype)notificationWithName:(NSString *)aName
object:(nullable id)anObject;
+ (instancetype)notificationWithName:(NSString *)aName
object:(nullable id)anObject
userInfo:(nullable NSDictionary *)aUserInfo;
NSNotificationCenter 這個(gè)類是一個(gè)通知中心查吊,使用單例設(shè)計(jì)谐区,每個(gè)應(yīng)用程序都會(huì)有一個(gè)默認(rèn)的通知中心。用于調(diào)度通知的發(fā)送的接受逻卖。
// 注冊(cè)通知觀察者的方法
- (void)addObserver:(id)observer
selector:(SEL)aSelector
name:(nullable NSString *)aName
object:(nullable id)anObject;
// 發(fā)送通知消息的方法
- (void)postNotification:(NSNotification *)notification;
- (void)postNotificationName:(NSString *)aName
object:(nullable id)anObject;
- (void)postNotificationName:(NSString *)aName
object:(nullable id)anObject
userInfo:(nullable NSDictionary *)aUserInfo;
// 移除觀察者的方法
- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer
name:(nullable NSString *)aName
object:(nullable id)anObject;
<h3 id="notificationuse">通知的使用流程</h3>
? 定義一個(gè)事件到來時(shí)該執(zhí)行的方法:
// 接收通知事件的類必須實(shí)現(xiàn)一個(gè)擁有以下特征的通知處理器方法:
// - (void)方法名:(NSNotification *)通知;
- (void)execute:(NSNotification *)notification {
// do something when received notification
// notification.name is @"NOTIFICATION_NAME"
if(notification.object &&
[notification.object isKindOfClass:[Test class]]) {
// do something
}
}
? 注冊(cè)觀察者:
NSNotificationCenter * ncenter = [NSNotificationCenter defaultCenter];
[ncenter addObserver:self
selector:@selector(execute:)
name:@"NOTIFICATION_NAME"
object:nil];
使用默認(rèn)的通知中心宋列,上面代碼的意義的:觀察者 self 在收到名為 @"NOTIFICATION_NAME" 的事件時(shí)執(zhí)行 @selector(execute:),最后一個(gè)參數(shù)是表示會(huì)對(duì)哪個(gè)發(fā)送者對(duì)象發(fā)出的事件作出響應(yīng)评也,nil 時(shí)表示接受所有發(fā)送者的事件炼杖。
? 注激發(fā)事件灭返,即通知相應(yīng)的觀察者:
NSNotificationCenter * ncenter = [NSNotificationCenter defaultCenter];
[ncenter postNotificationName:@"NOTIFICATION_NAME"
object:nil];
// 或者用下面幾行代碼,明確的 notification 示例
Test *test = [[Test alloc] init];
NSNotification *notification = [NSNotification
notificationWithName:@"NOTIFICATION_NAME"
object:test];
[ncenter postNotification:notification];
這里的 object 參數(shù)對(duì)應(yīng)到方法 - (void)execute:(NSNotification *)notification 里的 notification.object, name 就是 notification.name坤邪。代碼到這里熙含,方法 - (void)execute:(NSNotification *)notification 就會(huì)得到執(zhí)行了。
說明:我們上面用的 [NSNotificationCenter defaultCenter] 是默認(rèn)的同一個(gè)實(shí)例艇纺,你也可以使用自己的 NSNotificationCenter怎静,如:NSNotificationCenter *notificationCenter = [[NSNotificationCenter alloc]init];事件只會(huì)在當(dāng)前的 NotificationCenter 中廣播,不同的 NotificationCenter 之間的事件通知互不相干黔衡。
? 觀察者如果對(duì)一些事件沒興趣了蚓聘,應(yīng)該從 NotificationCenter 中移除掉:
NSNotificationCenter * ncenter = [NSNotificationCenter defaultCenter];
[ncenter removeObserver:self
name:@"NOTIFICATION_NAME"
object:test]; // object與注冊(cè)時(shí)相同
<h3 id="queuenotification">異步或合并通知</h3>
NSNotificationQueue 類可以為通知中心提供隊(duì)列,因此使用此類可以通過異步方式發(fā)布或合并通知盟劫。合并通知是指(從隊(duì)列中)過濾掉與較早加入隊(duì)列的某個(gè)通知類似的通知的過程夜牡。
// 獲取當(dāng)前線程的默認(rèn)通知隊(duì)列
NSNotificationQueue *nqueue = [NSNotificationQueue defaultQueue];
// 為指定的通知中心創(chuàng)建通知隊(duì)列
NSNotificationCenter *ncenter = [NSNotificationCenter defaultCenter];
NSNotificationQueue *queue = [[NSNotificationQueue alloc]
initWithNotificationCenter:ncenter];
// 隊(duì)列發(fā)布通知
// 下面代碼以同步方式將變量 notif 中的通知添加到隊(duì)列中,并合并了同名的通知
[[NSNotificationQueue defaultQueue]
enqueueNotification:notif
postingStyle:NSPostNow
coalesceMask:NSNotificationCoalescingOnName
forModes:nil];
// 隊(duì)列刪除通知
// 下面代碼從執(zhí)行合并操作的隊(duì)列中刪除變量 notif 中的通知
[[NSNotificationQueue defaultQueue]
dequeueNotificationsMatching:notif
coalesceMask:NSNotificationNoCoalescing];
方法 enqueueNotification:postingStyle:coalesceMask:forModes: 可以設(shè)置發(fā)布樣式侣签、合并選項(xiàng)和支持的發(fā)布通知運(yùn)行模式塘装。
可以使用下列常數(shù)定義合并選項(xiàng):
- NSNotificationNoCoalescing 不合并通知,記錄所有通知
- NSNotificationCoalescingOnName 合并同名的通知影所,即僅記錄其中一條通知
- NSNotificationCoalescingOnSender 合并來自同一發(fā)送者的通知蹦肴,即僅記錄其中一條通知
發(fā)布樣式定義了將通知添加到隊(duì)列中的交互模式(同步/異步、在空閑時(shí)/立刻)型檀∪哂龋可以使用下列常量設(shè)置這些選項(xiàng):
- NSPostASAP 當(dāng)前的運(yùn)行循環(huán)結(jié)束時(shí),立刻以異步方式發(fā)布通知
- NSPostWhenIdle 當(dāng)運(yùn)行循環(huán)等待輸入數(shù)據(jù)或計(jì)時(shí)器事件時(shí)胀溺,以異步方式發(fā)布通知
- NSPostNow 在合并后立刻發(fā)布隊(duì)列中的通知,提供高效的同步行為皆看。這類行為不需要依賴運(yùn)行循環(huán)仓坞。
<h3 id="notificationsummary">小結(jié)</h3>
本章介紹了 Foundation 框架的通知機(jī)制,簡(jiǎn)要介紹了與通知相關(guān)的類和 API腰吟,并介紹了使用通知的基本步驟无埃。