代理
代理設計模式的作用:
? ? 1.A對象監(jiān)聽B對象的一些行為吭产,A成為B的代理? ??
? ? 2.B對象想告訴A對象一些事情橄霉,A成為B的代理
代理設計模式的總結:? ?
? ? ?如果你想監(jiān)聽別人的一些行為姓蜂,那么你就要成為別人的代理
? ? ?如果你想告訴別人一些事情医吊,那么就讓別人成為你的代理
代理設計模式的開發(fā)步驟
? ? * 1.擬一份協(xié)議(協(xié)議名字的格式:控件名 + Delegate),在協(xié)議里面聲明一些代理方法(一般代理方法都是@optional)
? ? * 2.聲明一個代理屬性:@property (nonatomic, weak) id<代理協(xié)議> delegate;
? ? * 3.在內(nèi)部發(fā)生某些行為時束莫,調(diào)用代理對應的代理方法览绿,通知代理內(nèi)部發(fā)生什么事
? ? * 4.設置代理:xxx.delegate = yyy;
? ? * 5.yyy對象遵守協(xié)議饿敲,實現(xiàn)代理方法
?代理和通知的區(qū)別?
代理:1個對象只能告訴另1個對象發(fā)生了什么事
通知:1個對象可以告訴N個對象發(fā)生了什么事
?KVC\KVO
- KVC(Key Value Coding)常見作用:給模型屬性賦值
- KVO(Key Value Observing)常用作用:監(jiān)聽模型屬性值的改變
- KVO的使用步驟
// cc監(jiān)聽了aa的name屬性的改變`
[aa addObserver:cc forKeyPath:@"name" options: NSKeyValueObservingOptionOld context:nil];
// cc得實現(xiàn)監(jiān)聽方法
/**
* 當監(jiān)聽到object的keyPath屬性發(fā)生了改變
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"監(jiān)聽到%@對象的%@屬性發(fā)生了改變, %@", object, keyPath, change);
}
通知(NSNotification)
一個完整的通知一般包含3個屬性:
- (NSString *)name; // 通知的名稱
- (id)object; // 通知發(fā)布者(是誰要發(fā)布通知)
- (NSDictionary *)userInfo; // 一些額外的信息(通知發(fā)布者傳遞給通知接收者的信息內(nèi)容)
初始化一個通知(NSNotification)對象
+ (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;
發(fā)布通知
通知中心(NSNotificationCenter)提供了相應的方法來幫助發(fā)布通知
- (void)postNotification:(NSNotification *)notification;
// 發(fā)布一個notification通知渠啤,可在notification對象中設置通知的名稱、通知發(fā)布者份名、額外信息等
- (void)postNotificationName:(NSString *)aName object:(id)anObject;
// 發(fā)布一個名稱為aName的通知,anObject為這個通知的發(fā)布者
- (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
// 發(fā)布一個名稱為aName的通知鲤孵,anObject為這個通知的發(fā)布者普监,aUserInfo為額外信息
注冊通知監(jiān)聽器
通知中心(NSNotificationCenter)提供了方法來注冊一個監(jiān)聽通知的監(jiān)聽器(Observer)
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
- observer:監(jiān)聽器凯正,即誰要接收這個通知
- aSelector:收到通知后,回調(diào)監(jiān)聽器的這個方法桑滩,并且把通知對象當做參數(shù)傳入
- aName:通知的名稱运准。如果為nil缭受,那么無論通知的名稱是什么,監(jiān)聽器都能收到這個通知
- anObject:通知發(fā)布者韭畸。如果為anObject和aName都為nil陆盘,監(jiān)聽器都收到所有的通知
- (id)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block;
- name:通知的名稱
- obj:通知發(fā)布者
- block:收到對應的通知時败明,會回調(diào)這個block
- queue:決定了block在哪個操作隊列中執(zhí)行妻顶,如果傳nil,默認在當前操作隊列中同步執(zhí)行
取消注冊通知監(jiān)聽器
- 通知中心不會保留(retain)監(jiān)聽器對象幔嗦,在通知中心注冊過的對象邀泉,必須在該對象釋放前取消注冊汇恤。否則拔恰,當相應的通知再次出現(xiàn)時颜懊,通知中心仍然會向該監(jiān)聽器發(fā)送消息风皿。因為相應的監(jiān)聽器對象已經(jīng)被釋放了匠璧,所以可能會導致應用崩潰
- 通知中心提供了相應的方法來取消注冊監(jiān)聽器
- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;
- 一般在監(jiān)聽器銷毀之前取消注冊(如在監(jiān)聽器中加入下列代碼):
- (void)dealloc {
//[super dealloc];? 非ARC中需要調(diào)用此句
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
UIDevice通知
- UIDevice類提供了一個單粒對象鲁僚,它代表著設備裁厅,通過它可以獲得一些設備相關的信息拓挥,比如電池電量值(batteryLevel)、電池狀態(tài)(batteryState)盖灸、設備的類型(model赁炎,比如iPod、iPhone等)姻报、設備的系統(tǒng)(systemVersion)
- 通過[UIDevice currentDevice]可以獲取這個單粒對象
?UIDevice對象會不間斷地發(fā)布一些通知吴旋,下列是UIDevice對象所發(fā)布通知的名稱常量:
UIDeviceOrientationDidChangeNotification // 設備旋轉(zhuǎn)
?UIDeviceBatteryStateDidChangeNotification // 電池狀態(tài)改變
?UIDeviceBatteryLevelDidChangeNotification // 電池電量改變
?UIDeviceProximityStateDidChangeNotification // 近距離傳感器(比如設備貼近了使用者的臉部)
鍵盤通知
?我們經(jīng)常需要在鍵盤彈出或者隱藏的時候做一些特定的操作,因此需要監(jiān)聽鍵盤的狀態(tài)
?鍵盤狀態(tài)改變的時候,系統(tǒng)會發(fā)出一些特定的通知
?UIKeyboardWillShowNotification // 鍵盤即將顯示
?UIKeyboardDidShowNotification // 鍵盤顯示完畢
?UIKeyboardWillHideNotification // 鍵盤即將隱藏
?UIKeyboardDidHideNotification // 鍵盤隱藏完畢
?UIKeyboardWillChangeFrameNotification // 鍵盤的位置尺寸即將發(fā)生改變
?UIKeyboardDidChangeFrameNotification // 鍵盤的位置尺寸改變完畢
?系統(tǒng)發(fā)出鍵盤通知時,會附帶一下跟鍵盤有關的額外信息(字典),字典常見的key如下:
?UIKeyboardFrameBeginUserInfoKey // 鍵盤剛開始的frame
?UIKeyboardFrameEndUserInfoKey // 鍵盤最終的frame(動畫執(zhí)行完畢后)
?UIKeyboardAnimationDurationUserInfoKey // 鍵盤動畫的時間
?UIKeyboardAnimationCurveUserInfoKey // 鍵盤動畫的執(zhí)行節(jié)奏(快慢)
通知和代理的選擇
共同點
- 利用通知和代理都能完成對象之間的通信
(比如A對象告訴D對象發(fā)生了什么事情, A對象傳遞數(shù)據(jù)給D對象)
不同點
- 代理 : 1個對象只能告訴另1個對象發(fā)生了什么事情
- 通知 : 1個對象能告訴N個對象發(fā)生了什么事情, 1個對象能得知N個對象發(fā)生了什么事情