前言
通知中心是一個單例。通知在iOS
中是一種設計模式。每一個應用程序都有一個通知中心NSNotificationCenter
實例, 專門負責協助不同對象之間的消息通信.
任何一個對象都可以向通知中心發佈NSNotification
, 描述自己在做什麼,而任何註冊了該通知的對象該特定通知發佈的時候會收到這個通知。
獲取通知中心對象
通過下面的方式來獲取通知中心對象:
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
通知對象主要屬性
一個完整通知,也就是NSNotification
對象,有下面這三個主要的屬性:
@property (readonly, copy) NSString *name;
@property (nullable, readonly, retain) id object;
@property (nullable, readonly, copy) NSDictionary *userInfo;
其中,第一個就是通知的名稱,第二個是通知發佈者,而第三個就是一些額外的信息。比如第三個可以存儲一些數據,這樣接收者就可以接收到這些數據了。
通知對象初始化方法
初始化一個通知對象,有這幾個方法:
- (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;
蘋果還提供了一個初始化方法,但是蘋果要求不能使用:
/* do not invoke; not a valid initializer for this class */
- (instancetype)init /*NS_UNAVAILABLE*/;
發佈通知
通知的發佈,需要通過通知中心NSNotificationCenter
來發布。發佈通知中幾個三個方法:
- (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)addObserver:(id)observer
selector:(SEL)aSelector
name:(nullable NSString *)aName
object:(nullable id)anObject;
- (id <NSObject>)addObserverForName:(nullable NSString *)name
object:(nullable id)obj
queue:(nullable NSOperationQueue *)queue
usingBlock:(void (^)(NSNotification *note))block
第一個方法使用的方式是最多的,第二個方法很少見到使用。第二個方法是支持block
回調的,而queue
參數就是在哪個隊列。
取消註冊通知
通知註冊了,在不需要時還需要移除註冊。通知中心不會保留監聽器對象, 在通知中心註冊過的對象,必須在該對象釋放前取消註冊. 否則,當相應的通知再次出現時, 通知中心仍然會向該監聽器發送消息. 因爲, 相應的監聽器對象已經被釋放了, 所以可能會導致應用崩潰,這種崩潰很常見。
蘋果提供了兩個方法,可以移除註冊:
- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer
name:(nullable NSString *)aName
object:(nullable id)anObject;
通常,我們會在控制器的dealloc
之前,先取消註冊通知:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
如果我們只是想取消某一個通知的註冊,而不是全部,那麼可以使用第二個方法,將通知名稱傳過去,就會只取消註冊該通知。
鍵盤通知
對於鍵盤,我們經常需要註冊與移除註冊通知:
UIKeyboardWillShowNotification // 鍵盤即將顯示
UIKeyboardDidShowNotification // 鍵盤顯示完畢
UIKeyboardWillHideNotification // 鍵盤即將隱藏
UIKeyboardDidHideNotification // 鍵盤隱藏完畢
UIKeyboardWillChangeFrameNotification // 鍵盤的位置尺寸即將發生改變
UIKeyboardDidChangeFrameNotification // 鍵盤的位置尺寸改變完畢