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

看一遍就會哦!

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

通知

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

  • NSNotificationCenter 單進程通知管理
  • NSDistributedNotificationCenter 一臺機器中多個進程的通知管理

NSNotificationCenter

每個進程都包含一個默認的通知中心,這個通知中心是一個單例,通過[NSNotificationCenter defaultCenter]來獲取。

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

開發(fā)以來,感覺通知常用的場景有兩個:

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

創(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;

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

  • name:通知的名字,是通知能夠被接收到的關鍵因素。
  • object:通知發(fā)送者希望發(fā)送給觀察者的一個對象,通常為通知發(fā)送者自己。
  • userInfo:一個字典,是通知發(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;

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

注冊通知

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

在需要接收通知的位置注冊通知,注冊通知時需要設置:

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

移除通知

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

移除通知是很重要的操作,因為通知中心是不會保留(retain)觀察者對象的,在通知中心注冊過的觀察者,必須在觀察者對象釋放前取消注冊。否則,當相應的通知再次出現(xiàn)時,通知中心仍然會向該觀察者發(fā)送消息。因為相應的觀察者對象已經(jīng)被釋放了,所以可能會導致應用崩潰。
取消注冊的代碼一般寫在dealloc函數(shù)或者viewWillDisappear函數(shù)中。

舉個栗子

光說不練假把式。下面展示一個簡單的例子,在當前頁面dimiss的時候通過notification給上一個頁面?zhèn)髦怠?/p>

ViewController1
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    //注冊通知
    [[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ù)
    NSDictionary *dict =[[NSDictionary alloc] initWithObjectsAndKeys:@"我是一個參數(shù)",@"param", nil];
    //創(chuàng)建通知
    NSNotification *notification =[NSNotification notificationWithName:@"notify" object:nil userInfo:dict];
    //通過通知中心發(fā)送通知
    [[NSNotificationCenter defaultCenter] postNotification:notification];
    [self dismissViewControllerAnimated:YES completion:nil];
}

NSDistributedNotificationCenter

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

┌(???)?有用的話,動動

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

相關閱讀更多精彩內容

友情鏈接更多精彩內容