Objective-C 學(xué)習(xí)筆記 - 第12章 通知中心

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腰吟,并介紹了使用通知的基本步驟无埃。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市毛雇,隨后出現(xiàn)的幾起案子嫉称,更是在濱河造成了極大的恐慌,老刑警劉巖灵疮,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件织阅,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡震捣,警方通過查閱死者的電腦和手機(jī)荔棉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門闹炉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人润樱,你說我怎么就攤上這事渣触。” “怎么了壹若?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵嗅钻,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我店展,道長(zhǎng)啊犬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任壁查,我火速辦了婚禮觉至,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘睡腿。我一直安慰自己语御,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布席怪。 她就那樣靜靜地躺著应闯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪挂捻。 梳的紋絲不亂的頭發(fā)上碉纺,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音刻撒,去河邊找鬼骨田。 笑死,一個(gè)胖子當(dāng)著我的面吹牛声怔,可吹牛的內(nèi)容都是我干的态贤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼醋火,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼悠汽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起芥驳,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤柿冲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后兆旬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體假抄,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡袱蜡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年梢卸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冠摄。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡阁吝,死狀恐怖声登,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蛉签,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站妈经,受9級(jí)特大地震影響吹泡,放射性物質(zhì)發(fā)生泄漏经瓷。R本人自食惡果不足惜爆哑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望舆吮。 院中可真熱鬧揭朝,春花似錦、人聲如沸色冀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呐伞。三九已至敌卓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間伶氢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工瘪吏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留癣防,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓掌眠,卻偏偏與公主長(zhǎng)得像蕾盯,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蓝丙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容