高效開(kāi)發(fā)之NSNotificationCenter使用指南

看一遍就會(huì)哦!

最近又干回了我的老本行 - iOS,感覺(jué)自己的邏輯思維比以前嚴(yán)密了許多,但是也發(fā)現(xiàn)有很多知識(shí)沒(méi)有掌握牢靠。在使用NSNotification時(shí)竟發(fā)現(xiàn)有些手生,趕緊抽時(shí)間整理一波,授人玫瑰,手有余香。
本文內(nèi)容參考自官方API Reference

通知

Notification就是一個(gè)消息通知機(jī)制,類(lèi)似廣播。觀察者向消息中心注冊(cè)感興趣的東西,當(dāng)感興趣的東西發(fā)出這個(gè)消息的時(shí)候,觀察者就能接受到通知,然后去做相對(duì)應(yīng)的事情。使用消息通知可以起到多個(gè)對(duì)象之間解耦的作用。蘋(píng)果封裝了常用的一些通知,比如窗口獲得焦點(diǎn)、網(wǎng)絡(luò)連接關(guān)閉等事件信息等。當(dāng)然,我們也可以自定義個(gè)性化的通知。
通知中心,就是分發(fā)這些通知的地方,Cocoa框架中有兩種通知中心:

  • NSNotificationCenter 單進(jìn)程通知管理
  • NSDistributedNotificationCenter 一臺(tái)機(jī)器中多個(gè)進(jìn)程的通知管理

NSNotificationCenter

每個(gè)進(jìn)程都包含一個(gè)默認(rèn)的通知中心,這個(gè)通知中心是一個(gè)單例,通過(guò)[NSNotificationCenter defaultCenter]來(lái)獲取。

通知中心將通知分發(fā)給觀察者處理采用了同步機(jī)制,即當(dāng)某一個(gè)通知被發(fā)送時(shí),會(huì)一直阻塞在發(fā)送方法內(nèi),直到通知中心將該通知分發(fā)給注冊(cè)過(guò)的觀察者并且觀察者完成了相應(yīng)的處理之后,發(fā)送者才能繼續(xù)執(zhí)行其所在線(xiàn)程內(nèi)的后續(xù)代碼。如果要使用異步機(jī)制發(fā)送通知,文章后面會(huì)講到“通知隊(duì)列”,即第二種通知中心。

開(kāi)發(fā)以來(lái),感覺(jué)通知常用的場(chǎng)景有兩個(gè):

  1. 當(dāng)前頁(yè)面給上一個(gè)頁(yè)面?zhèn)髦怠?/li>
  2. 當(dāng)一個(gè)值發(fā)生改變時(shí),相應(yīng)的對(duì)象作出相應(yīng)的操作。

創(chuàng)建通知

- (instancetype)initWithName:(NSNotificationName)name object:(nullable id)object userInfo:(nullable NSDictionary *)userInfo;
+ (instancetype)notificationWithName:(NSNotificationName)aName object:(nullable id)anObject;
+ (instancetype)notificationWithName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;

這三個(gè)方法都能成功的創(chuàng)建一個(gè)通知,然而創(chuàng)建通知并不是必要的操作,因?yàn)樵诎l(fā)送通知時(shí),可以包含通知的各項(xiàng)參數(shù)。但是單獨(dú)講一下可以加深理解嘛。???
從上面三個(gè)方法可以看出,一個(gè)通知包含以下幾個(gè)參數(shù):

  • name:通知的名字,是通知能夠被接收到的關(guān)鍵因素。
  • object:通知發(fā)送者希望發(fā)送給觀察者的一個(gè)對(duì)象,通常為通知發(fā)送者自己。
  • userInfo:一個(gè)字典,是通知發(fā)送者傳遞給觀察者的參數(shù)。

發(fā)布通知

- (void)postNotification:(NSNotification *)notification;
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject;
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;

第一個(gè)方法適用于發(fā)布已經(jīng)通過(guò)NSNotification創(chuàng)建好的通知,其余兩個(gè)方法就在發(fā)布通知的時(shí)候,寫(xiě)入了通知的具體參數(shù)。

注冊(cè)通知

- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;

在需要接收通知的位置注冊(cè)通知,注冊(cè)通知時(shí)需要設(shè)置:

  • observer:觀察者,通常是self。
  • selector:收到通知后,回調(diào)監(jiān)聽(tīng)器的這個(gè)方法,并且把通知對(duì)象當(dāng)做參數(shù)傳入。
  • name:通知的名稱(chēng),決定了觀察者所接收的通知。如果為nil,那么觀察者會(huì)接收到所有通知。
  • object:通知的發(fā)布者。
    注冊(cè)完通知之后就可以靜靜等待獵物的到來(lái)了。

移除通知

- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;

移除通知是很重要的操作,因?yàn)橥ㄖ行氖遣粫?huì)保留(retain)觀察者對(duì)象的,在通知中心注冊(cè)過(guò)的觀察者,必須在觀察者對(duì)象釋放前取消注冊(cè)。否則,當(dāng)相應(yīng)的通知再次出現(xiàn)時(shí),通知中心仍然會(huì)向該觀察者發(fā)送消息。因?yàn)橄鄳?yīng)的觀察者對(duì)象已經(jīng)被釋放了,所以可能會(huì)導(dǎo)致應(yīng)用崩潰。
取消注冊(cè)的代碼一般寫(xiě)在dealloc函數(shù)或者viewWillDisappear函數(shù)中。

舉個(gè)栗子

光說(shuō)不練假把式。下面展示一個(gè)簡(jiǎn)單的例子,在當(dāng)前頁(yè)面dimiss的時(shí)候通過(guò)notification給上一個(gè)頁(yè)面?zhèn)髦怠?/p>

ViewController1
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    //注冊(cè)通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notifyReceived:) name:@"notify" object:nil];
}
- (void)notifyReceived:(NSNotification *)content {
    NSLog(@"-----接收到通知------");
    NSLog(@"%@", content.userInfo[@"param"]);
}
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    //移除通知
    [[NSNotificationCenter defaultCenter] removeObserve:self];
}

ViewController2
- (void)gotoNextVC {
    //設(shè)置需要傳遞的參數(shù)
    NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:@"我是一個(gè)參數(shù)",@"param", nil];
    //創(chuàng)建通知
    NSNotification *notification =[NSNotification notificationWithName:@"notify" object:nil userInfo:dict];
    //通過(guò)通知中心發(fā)送通知
    [[NSNotificationCenter defaultCenter] postNotification:notification];
    [self dismissViewControllerAnimated:YES completion:nil];
}

NSDistributedNotificationCenter

分布式通知中心。這里就使用到了通知隊(duì)列(Notification queue),通知隊(duì)列通常以先進(jìn)先出的順序管理通知,當(dāng)一個(gè)通知到達(dá)隊(duì)首時(shí),通知隊(duì)列就將這個(gè)通知發(fā)送給通知中心,通知中心將其派發(fā)給所有監(jiān)聽(tīng)它的觀察者們。
每一個(gè)線(xiàn)程都有一個(gè)默認(rèn)的通知隊(duì)列,也是一個(gè)單例,通過(guò)[NSNotificationQueue defaultQueue]獲取。我們也可以自定義通知隊(duì)列,每個(gè)通知中心和線(xiàn)程可以有多個(gè)隊(duì)列。
這個(gè)就不細(xì)講了,如果下次有用到,會(huì)結(jié)合實(shí)際情況再進(jìn)行總結(jié)的。

┌(???)?有用的話(huà),動(dòng)動(dòng)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容