? ? ? ?原生KVO的實(shí)現(xiàn)依賴(lài)于強(qiáng)大的runtime運(yùn)行時(shí)機(jī)制冷尉,實(shí)現(xiàn)原理大致為:當(dāng)觀(guān)察某對(duì)象A的屬性時(shí)允耿,會(huì)動(dòng)態(tài)的創(chuàng)建這個(gè)類(lèi)的子類(lèi),并為這個(gè)新的子類(lèi)重寫(xiě)了Setter方法,在這個(gè)Setter方法里面負(fù)責(zé)通知觀(guān)察者屬性變化的情況距潘。
? ? ? ?前段時(shí)間面試的時(shí)候,面試官問(wèn)我只搁,如果不用系統(tǒng)的KVO模式音比,自己來(lái)實(shí)現(xiàn)一種設(shè)計(jì)模式,當(dāng)時(shí)可能由于緊張氢惋,一下子沒(méi)反應(yīng)過(guò)來(lái)洞翩,最后結(jié)果可想而知,現(xiàn)在想來(lái)明肮,對(duì)比現(xiàn)在所在的外包公司的種種不公平待遇菱农,總結(jié)下來(lái)一句話(huà),肚子里沒(méi)貨還真不行柿估。
? ? ? 閑話(huà)不多扯循未,先來(lái)簡(jiǎn)單說(shuō)一下如何自己實(shí)現(xiàn)NSNotificationCenter通知模式,然后秫舌,細(xì)聊如何通過(guò)協(xié)議實(shí)現(xiàn)KVO的妖,不同于原生KVO的實(shí)現(xiàn)方案。
? ? ? 通知中心實(shí)現(xiàn)方案足陨,首先進(jìn)行角色劃分嫂粟,一個(gè)單例類(lèi)A+抽象協(xié)議接口(包含接收到通知后實(shí)現(xiàn)的接口和發(fā)出通知的接口)Protocol+具體的實(shí)現(xiàn)類(lèi)B;
? ? ? ??客戶(hù)端: ? ?A ? 包含屬性數(shù)組 ?墨缘,B遵循Protocol星虹,實(shí)現(xiàn)協(xié)議方法,A數(shù)組持有B對(duì)象镊讼,當(dāng)A發(fā)出通知時(shí)宽涌,取出數(shù)組中的B對(duì)象,通過(guò)運(yùn)行時(shí)蝶棋,讓B實(shí)現(xiàn)協(xié)議方法卸亮,從而達(dá)到通知的目的。
這里玩裙,我們重點(diǎn)看一下KVO的實(shí)現(xiàn)方案兼贸,首先進(jìn)行角色劃分:
第一步 : 抽象出接口:所有觀(guān)察者必須遵循這個(gè)協(xié)議
// 抽象觀(guān)察者Observer
@protocol Observer
- (void)update:(Observable *)o msg:(NSObject *)msg;
@end
第二步:定義一個(gè)基類(lèi)Observable,所有被觀(guān)察者對(duì)象都必須繼承于Observable基類(lèi)
// 注冊(cè)觀(guān)察者- (void)addObserver:(id)o; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
// 刪除觀(guān)察者- (void)deleteObserver:(id)o;// 刪除所有觀(guān)察者
- (void)deleteObservers;// 觀(guān)察者數(shù)量
- (NSInteger)countObserver;// 通知
- (void)notifyObservers;- (void)notifyObservers:(NSObject *)msg;
// 更新數(shù)據(jù)
- (void)setChanged;// 取消更新
- (void)clearChanged;// 獲取更新?tīng)顟B(tài)
- (BOOL)hasChanged;
Observable.m文件實(shí)現(xiàn):
#import "Observable.h"@interface Observable()
@property (nonatomic,strong) NSMutableArray *obsArray;
@property (nonatomic,assign) BOOL changed;
@end
// 被觀(guān)察者
@implementation Observable
- (instancetype)init{?
? ? ? ?if (self = [super init]) {? ?
? ? ?_obsArray = [NSMutableArray array];? ? ? ?
?_changed = NO;? ? }?
? return self;}
// 注冊(cè)觀(guān)察者
- (void)addObserver:(id)o {? ? [_obsArray addObject:o];}
// 刪除觀(guān)察者
- (void)deleteObserver:(id)o {? ? [_obsArray removeObject:o];}
// 刪除所有觀(guān)察者
- (void)deleteObservers {? ? [_obsArray removeAllObjects];}
// 觀(guān)察者數(shù)量
- (NSInteger)countObserver?{? ? return _obsArray.count;}
- (void)notifyObservers {? ? [self notifyObservers:nil];}
- (void)notifyObservers:(NSObject *)msg
{? ?
? ? if (!_changed)?{? ? ? ? return ;? ? }? ?
? ? [self clearChanged];? ?
? ? ?for (idobj in _obsArray) {
[obj update:self msg:msg];
}
}
// 更新數(shù)據(jù)
- (void)setChanged {
_changed = YES;
}
// 取消更新
- (void)clearChanged {
_changed = NO吃溅;
}
// 獲取更新?tīng)顟B(tài)
- (BOOL)hasChanged {
return _changed;
}
客戶(hù)端實(shí)現(xiàn):
WXObservable *observable = [WXObservable new];
[observable addObserver:[CoffeeObserver new]];
[observable addObserver:[SimpleObserver new]];
[observable setTitle:@"思維的切換"];
[observable push];
[observable push];
[observable push];