A.定義
iOS程序都有一個NSNotificationCenter的單例對象,用來負責發布不同對象之間的通知
任何對象都能夠在NSNotificationCenter發布通知,發布自己的發生的事件;監聽者(Observer)可以選擇接受某個特定通知。
B.使用
1. 屬性
- - (NSDictionary*)userInfo; // 一些額外的信息(通知發布者傳遞給通知接收者的信息內容)
2.初始化
- + (instancetype)notificationWithName:(NSString*)aName object:(id)anObject;
- + (instancetype)notificationWithName:(NSString*)aName object:(id)anObject userInfo:(NSDictionary*)aUserInfo;
- - (instancetype)initWithName:(NSString*)name object:(id)object userInfo:(NSDictionary *)userInfo;
3.發布通知(通過NSNotificationCenter)
- (void)postNotification:(NSNotification*)notification;
發布一個notification通知,可在notification對象中設置通知的名稱、通知發布者、額外信息等
- (void)postNotificationName:(NSString*)aName object:(id)anObject;
發布一個名稱為aName的通知,anObject為這個通知的發布者
- (void)postNotificationName:(NSString*)aName object:(id)anObject userInfo:(NSDictionary*)aUserInfo;
發布一個名稱為aName的通知,anObject為這個通知的發布者,aUserInfo為額外信息
4.設置監聽器Observer
通知中心(NSNotificationCenter)提供了方法來注冊一個監聽通知的監聽器(Observer)
(1)
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString*)aName object:(id)anObject;
aSelector:收到通知后,回調監聽器的這個方法,并且把通知對象當做參數傳入
aName:通知的名稱。如果為nil,那么無論通知的名稱是什么,監聽器都能收到這個通知
anObject:通知發布者。如果為anObject和aName都為nil,監聽器都收到所有的通知
(2)
- (id)addObserverForName:(NSString*)name object:(id)obj queue:(NS
OperationQueue*)queue usingBlock:(void (^)(NSNotification*note))block;
block:收到對應的通知時,會回調這個block
queue:決定了block在哪個操作隊列中執行,如果傳nil,默認在當前操作隊列中同步執行
5.在監聽器銷毀之前,取消監聽
通知中心不會保留(retain)監聽器對象,在通知中心注冊過的對象,必須在該對象釋放前取消注冊。否則,當相應的通知再次出現時,通知中心仍然會向該監聽器發送消息。因為相應的監聽器對象已經被釋放了,所以可能會導致應用崩潰
通知中心提供了相應的方法來取消注冊監聽器
- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(NSString*)aName object:(id)anObject;
一般在監聽器銷毀之前取消注冊(如在監聽器中加入下列代碼):
- (void)dealloc {
//[super dealloc]; 非ARC中需要調用此句
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
C.iOS中自帶的通知 UIDevice
UIDevice類提供了一個單例對象,它代表著設備,通過它可以獲得一些設備相關的信息,比如電池電量值(batteryLevel)、電池狀態(batteryState)、設備的類型(model,比如
ipod、iPhone等)、設備的系統(systemVersion)
通過[UIDevice currentDevice]可以獲取這個單例對象
UIDevice對象會不間斷地發布一些通知,下列是UIDevice對象所發布通知的名稱常量:
UIDeviceOrientationDidChangeNotification// 設備旋轉
UIDeviceBatteryStateDidChangeNotification// 電池狀態改變
UIDeviceBatteryLevelDidChangeNotification // 電池電量改變
UIDevice
PRoximityStateDidChangeNotification// 近距離傳感器(比如設備貼近了使用者的臉部)
D.鍵盤通知
我們經常需要在鍵盤彈出或者隱藏的時候做一些特定的操作,因此需要監聽鍵盤的狀態
UIKeyboardWillShowNotification // 鍵盤即將顯示
UIKeyboardDidShowNotification //鍵盤顯示完畢
UIKeyboardWillHideNotification // 鍵盤即將隱藏
UIKeyboardDidHideNotification // 鍵盤隱藏完畢
UIKeyboardWillChangeFrameNotification // 鍵盤的位置尺寸即將發生改變
UIKeyboardDidChangeFrameNotification //鍵盤的位置尺寸改變完畢
系統發出鍵盤通知時,會附帶一下跟鍵盤有關的額外信息(字典),字典常見的key如下:
UIKeyboardFrameBeginUserInfoKey // 鍵盤剛開始的frame
UIKeyboardFrameEndUserInfoKey // 鍵盤最終的frame(動畫執行完畢后)
UIKeyboardAnimationDurationUserInfoKey // 鍵盤動畫的時間
UIKeyboardAnimationCurveUserInfoKey // 鍵盤動畫的執行節奏(快慢)
E.通知和代理的異同
共同點
利用通知和代理都能完成對象之間的通信
(比如A對象告訴D對象發生了什么事情, A對象傳遞數據給D對象)
不同點
代理 :一對一關系(1個對象只能告訴另1個對象發生了什么事情)
通知 :多對多關系(1個對象能告訴N個對象發生了什么事情, 1個對象能得知N個對象發生了什么事情)
F.練習
模擬敵我電臺向外發布消息,我方人員接收我方電臺,敵方人員接收敵方電臺,內奸可以接收雙方電臺
1 // 2 // Radio.h 3 // Notification 4 // 5 // Created by hellovoidworld on 14/12/7. 6 // Copyright (c) 2014年 hellovoidworld. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h>10 11 @interface Radio : NSObject12 13 // 電臺名稱14 @property(nonatomic, copy) NSString *name;15 16 @end
1 // 2 // Radio.m 3 // Notification 4 // 5 // Created by hellovoidworld on 14/12/7. 6 // Copyright (c) 2014年 hellovoidworld. All rights reserved. 7 // 8 9 #import "Radio.h"10 11 @implementation Radio12 13 @end
1 // 2 // main.m 3 // Notification 4 // 5 // Created by hellovoidworld on 14/12/7. 6 // Copyright (c) 2014年 hellovoidworld. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h>10 #import "Radio.h"11 #import "Person.h"12 13 int main(int argc, const char * argv[]) {14 @autoreleasepool {15 Radio *r1 = [[Radio alloc] init];16 r1.name = @"我方電臺";17 18 Radio *r2 = [[Radio alloc] init];19 r2.name = @"敵方電臺";20 21 // 僅能接收我方電臺消息22 Person *p1 = [[Person alloc] init];23 p1.role = @"我方忠心耿耿的戰士";24 25 // 僅能接收敵方電臺消息26 Person *p2 = [[Person alloc] init];27 p2.role = @"敵方可惡的走狗";28 29 // 技能接收我方電臺消息,也能接收敵方電臺消息30 Person *p3 = [[Person alloc] init];31 p3.role = @"潛伏在我方狡猾的內奸";32 33 // 嗯,我是傳播電臺電波的媒介34 NSNotificationCenter *center = [NSNotificationCenter defaultCenter];35 36 // 1.添加監聽器37 [center addObserver:p1 selector:@selector(receiveInfoFromRadio:) name:@"attack" object:r1];38 [center addObserver:p2 selector:@selector(receiveInfoFromRadio:) name:@"defend" object:r2];39 [center addObserver:p3 selector:@selector(receiveInfoFromRadio:) name:@"attack" object:r1];40 [center addObserver:p3 selector:@selector(receiveInfoFromRadio:) name:@"defend" object:r2];41 42 // 2.我方電臺r1發布攻擊信息43 [center postNotificationName:@"attack" object:r1 userInfo:@{@"title":@"attack!, all the money belong to us!", @"title2":@"And the girls!!!"}];44 45 // 3.敵方電臺r2發布回防信息46 [center postNotificationName:@"defend" object:r2 userInfo:@{@"title":@"TP back quickly!"}];47 48 }49 return 0;50 }
out:
2014-12-07 21:18:03.142 Notification[7923:714964] 我是我方忠心耿耿的戰士, 正在接受我方電臺的消息, 內容是{
title = "attack!, all the money belong to us!";
title2 = "And the girls!!!";
}
2014-12-07 21:18:03.143 Notification[7923:714964] 我是潛伏在我方狡猾的內奸, 正在接受我方電臺的消息, 內容是{
title = "attack!, all the money belong to us!";
title2 = "And the girls!!!";
}
2014-12-07 21:18:03.143 Notification[7923:714964] 我是敵方可惡的走狗, 正在接受敵方電臺的消息, 內容是{
title = "TP back quickly!";
}
2014-12-07 21:18:03.143 Notification[7923:714964] 我是潛伏在我方狡猾的內奸, 正在接受敵方電臺的消息, 內容是{
title = "TP back quickly!";
}
Program ended with exit code: 0