您好,登錄后才能下訂單哦!
觀察者設(shè)計(jì)模式
KVO也叫 “發(fā)布--訂閱”模式,很像雜志的訂閱。
讀者把名字和郵寄地址提供給發(fā)行商
發(fā)行商在發(fā)行新一期的的雜志時(shí),就能將雜志送到每一個(gè)讀者手中
原理:
訂閱者注冊(cè)成為發(fā)布者的某一屬性的觀察者
當(dāng)發(fā)布者的這一屬性發(fā)生變化時(shí),所有的觀察者都會(huì)得知該屬性的變化
KVC(鍵值編碼)是實(shí)現(xiàn)KVO的基礎(chǔ)
與代理的功能類似,用來(lái)實(shí)現(xiàn):對(duì)象間傳遞事件、數(shù)值,但不能為自身屬性賦值
觀察者設(shè)計(jì)的使用步驟
1)發(fā)布者添加屬性
如一個(gè)Person類,添加屬性age
@interface AMPerson : NSObject @property (nonatomic, strong) NSNumber* age; @end
2)注冊(cè)成為訂閱者
發(fā)布者調(diào)用addObserver:forKeyPath:options:context:方法,注冊(cè)其指定屬性的訂閱者
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
如控制器創(chuàng)建一個(gè)Person對(duì)象,并成為其訂閱者
self.person = [[AMPerson alloc] init]; self.person.age = @10; [self.person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];
3)訂閱者實(shí)現(xiàn)observeValueForKeyPath:ofObject:change:context:方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
如:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { if ( [keyPath isEqualToString:@"age"] ) { NSLog(@"%@", change); } }
4)發(fā)布者的屬性發(fā)生變化時(shí)訂閱者會(huì)響應(yīng)
響應(yīng)方法即發(fā)布者的observeValueForKeyPath:ofObject:change:context:方法
注意:必須使用KVC的賦值方式訂閱者才會(huì)響應(yīng)
如:
NSInteger age = self.person.age.integerValue+1; [self.person setValue:@(age) forKey:@"age"];
5)訂閱者銷毀前將注冊(cè)信息刪除
發(fā)布者使用removeObserver:forKeyPath:方法刪除指定的訂閱者
- (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
如:
- (void)dealloc { [self.person removeObserver:self forKeyPath:@"age"]; }
通知機(jī)制
通知機(jī)制是基于觀察者設(shè)計(jì)模式實(shí)現(xiàn)一種對(duì)象間的通信技術(shù)。
雖然Objective-C的對(duì)象支持直接使用觀察者設(shè)計(jì)模式開(kāi)發(fā),但通知機(jī)制的使用過(guò)程更加簡(jiǎn)單
通知中心是一種多對(duì)多的通信方式,而觀察者僅僅是一對(duì)多的通信方式
通知中心:
每個(gè)應(yīng)用程序都有一個(gè)實(shí)現(xiàn)通知機(jī)制的實(shí)例,稱作通知中心(NSNotificationCenter)
獲得其單例對(duì)象:
+ (NSNotificationCenter *)defaultCenter
通知中心還包含添加、刪除通知關(guān)系的方法
通知的發(fā)布者:
任何對(duì)象都可以向通知中心發(fā)布消息
通知的接受者:(響應(yīng)者)
任何對(duì)象都可以在通知中心注冊(cè)所關(guān)心的消息,并在關(guān)系消息被發(fā)布時(shí)收到
通知對(duì)象(NSNotification)主要包含以下三個(gè)屬性:
@property(readonly, copy) NSString *name //通知名 @property(readonly, retain) id object //通知的發(fā)布者 @property(readonly, copy) NSDictionary *userInfo //通知中可以攜帶的數(shù)據(jù)
通知的使用過(guò)程
1)起一個(gè)通知的名字
一般在發(fā)布者源文件中定義并在頭文件中聲明
//AMAppView.h extern NSString * const AMAppViewNameBtnClickedNotification; //AMAppView.m NSString * const AMAppViewNameBtnClickedNotification = @"AMAppViewNameBtnClickedNotification";
2)通知發(fā)布者通過(guò)通知中心發(fā)布通知
通知中心使用postNotification方法發(fā)布通知
- (void)postNotification:(NSNotification *)notification - (void)postNotificationName:(NSString *)notificationName object:(id)notificationSender - (void)postNotificationName:(NSString *)notificationName object:(id)notificationSender userInfo:(NSDictionary *)userInfo
如:
[[NSNotificationCenter defaultCenter] postNotificationName:AMAppViewNameBtnClickedNotification object:self userInfo:@{@"appModel":self.appModel}];
3)通知接收者通過(guò)通知中心注冊(cè)想要接收的通知
使用通知中心的addObserver方法
- (void)addObserver:(id)notificationObserver selector:(SEL)notificationSelectorname:(NSString *)notificationName object:(id)notificationSender - (id<NSObject>)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block
如:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appViewNameBtnClicked:) name:AMAppViewNameBtnClickedNotification object:v];
4)通知接收者實(shí)現(xiàn)通知的響應(yīng)方法或block
- (void) appViewNameBtnClicked:(NSNotification*) notification { NSLog(@"%@", notification.name); NSLog(@"%@", notification.object); NSLog(@"%@", notification.userInfo); }
5)通知接收者在被銷毀或者不再想接收通知時(shí),從通知中心移除
使用通知中心的removeObserver方法
- (void)removeObserver:(id)notificationObserver - (void)removeObserver:(id)notificationObserver name:(NSString *)notificationNameobject:(id)notificationSender
一般放在接受者的dealloc方法中調(diào)用,如:
- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
使用場(chǎng)景的區(qū)別:
代理設(shè)計(jì)模式:一對(duì)一的關(guān)系 對(duì)象間關(guān)系相對(duì)比較緊密
觀察者設(shè)計(jì)模式:一對(duì)多的關(guān)系
通知機(jī)制:多對(duì)多的關(guān)系
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。