iOS:KVO

KVO簡介

KVO<NSKeyValueObserving>昂灵,是一個非正式協(xié)議宗收,提供了一個途徑硼端,使對象(觀察者)能夠觀察其他對象(被觀察者)的屬性,當(dāng)被觀察者的屬性發(fā)生變化時醋安,觀察者就會被告知該變化。由NSKeyValueObserving協(xié)議提供支持墓毒,NSObject類繼承了該協(xié)議吓揪,所以NSObject的子類都可使用該方法。

基本方法

添加觀察者

/*
object : 被觀察對象
observer: 觀察對象
forKeyPath里面帶上property的name所计,如UIView的frame柠辞、center,如自定義對象的成員變量等等
options: 有4個值主胧,分別是:
NSKeyValueObservingOptionNew 把更改之后的值提供給處理方法
NSKeyValueObservingOptionOld 把更改之前的值提供給處理方法
NSKeyValueObservingOptionInitial 把初始化的值提供給處理方法叭首,一旦注冊习勤,立馬就會調(diào)用一次。通常它會帶有新值焙格,而不會帶有舊值图毕。
NSKeyValueObservingOptionPrior 分2次調(diào)用。在值改變之前和值改變之后眷唉。
context: 可以帶入一些參數(shù)予颤,其實這個挺好用的,任何類型都可以冬阳,自己強(qiáng)轉(zhuǎn)就好了
*/
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context

實現(xiàn)觀察者回調(diào)方法

/*
keyPath: 對應(yīng)forKeyPath
object:  被觀察的對象
change:  對應(yīng)options里的NSKeyValueObservingOptionNew蛤虐、NSKeyValueObservingOptionOld等
context: 對應(yīng)context
*/
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary*)change context:(nullable void *)context

移除觀察者

- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath

KVO模式

KVO分為自動和手動兩種模式
簡單的實現(xiàn)一個自動模式

//自動模式
- (void)viewDidLoad {
    [super viewDidLoad];
    Person *person = [[Person alloc] init];
    person.name = @"A";
    //NSLog(@"class:%s",object_getClassName(person));
    NSLog(@"before:%@",[self findSubClass:[person class]]);
    [person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
    NSLog(@"before:%@",[self findSubClass:[person class]]);
    //NSLog(@"class:%s",object_getClassName(person));
    person.name = @"B";
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    NSLog(@"%@",change);
}

/*
利用runtime獲取該類的所有子類
*/
- (NSArray *)findSubClass:(Class)defaultClass {
    int count = objc_getClassList(NULL,0);
    if (count <= 0) {
        return [NSArray array];
    }
    NSMutableArray *output = [NSMutableArray arrayWithObject:defaultClass];
    Class *classes = (Class *)malloc(sizeof(Class) * count);
    objc_getClassList(classes, count);
    for (int i = 0; i < count; i++) {
        if (defaultClass == class_getSuperclass(classes[i])) {
            [output addObject:classes[i]];
        }
    }
    return output;
}
image.png

實現(xiàn)一個手動模式,首先要明白KVO自動模式的實現(xiàn)原理:
如果原類為 Person肝陪,那么會自動生成一個繼承Person類的派生類笆焰,名為 NSKVONotifying_Person (見自動模式截圖),系統(tǒng)會偷偷將原類Person的isa 指針指向動態(tài)生成的派生類见坑,在給被監(jiān)控屬性賦值時執(zhí)行的其實是派生類的 setter 方法嚷掠,該派生類的setter方法中會增加willChangeValueForKey和didChangeValueForKey方法。

//手動模式
/*
需要在被觀察者對象(這里被觀察者是Pesron類)中重寫automaticallyNotifiesObserversForKey靜態(tài)方法
在這里荞驴,我僅針對成員變量name進(jìn)行手動
*/
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
    if ([key isEqualToString:@"name"]) {
        return NO;
    }
    return YES;
}

/*
手動模式就需要手動調(diào)用willChangeValueForKey和didChangeValueForKey兩個方法
*/
- (void)setName:(NSString *)name {
    [self willChangeValueForKey:@"name"];
    _name = name;
    [self didChangeValueForKey:@"name"];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    Person *person = [[Person alloc] init];
    person.name = @"A";
    [person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
    person.name = @"B";
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    NSLog(@"%@",change);
    NSLog(@"class:%@",[object class]);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末不皆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子熊楼,更是在濱河造成了極大的恐慌霹娄,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鲫骗,死亡現(xiàn)場離奇詭異犬耻,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)执泰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進(jìn)店門枕磁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人术吝,你說我怎么就攤上這事计济。” “怎么了排苍?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵沦寂,是天一觀的道長。 經(jīng)常有香客問我淘衙,道長传藏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮毯侦,結(jié)果婚禮上西壮,老公的妹妹穿的比我還像新娘。我一直安慰自己叫惊,他們只是感情好款青,可當(dāng)我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著霍狰,像睡著了一般抡草。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蔗坯,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天康震,我揣著相機(jī)與錄音,去河邊找鬼宾濒。 笑死腿短,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绘梦。 我是一名探鬼主播橘忱,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼卸奉!你這毒婦竟也來了钝诚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤榄棵,失蹤者是張志新(化名)和其女友劉穎凝颇,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疹鳄,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡拧略,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了瘪弓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垫蛆。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖杠茬,靈堂內(nèi)的尸體忽然破棺而出月褥,到底是詐尸還是另有隱情弛随,我是刑警寧澤瓢喉,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站舀透,受9級特大地震影響栓票,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一走贪、第九天 我趴在偏房一處隱蔽的房頂上張望佛猛。 院中可真熱鬧,春花似錦坠狡、人聲如沸继找。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽婴渡。三九已至,卻和暖如春凯亮,著一層夾襖步出監(jiān)牢的瞬間边臼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工假消, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留柠并,地道東北人。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓富拗,卻偏偏與公主長得像臼予,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子啃沪,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,860評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 上一篇:iOS-KVC淺談 前言:KVO 作為 KVC 的同袍兄弟瘟栖,功能更強(qiáng)大,聊聊 KVO谅阿。 一半哟、KVO 簡介 ...
    夢蕊dream閱讀 721評論 0 0
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時...
    歐辰_OSR閱讀 29,418評論 8 265
  • 什么是KVO KVO (Key-Value Observing) 是 Objective-C 對觀察者設(shè)計模式的一...
    壯骨閱讀 288評論 0 0
  • 一、概述 KVO签餐,即:Key-Value Observing寓涨,它提供一種機(jī)制,當(dāng)指定的對象的屬性被修改后氯檐,則其觀察...
    DeerRun閱讀 10,087評論 11 33
  • 之前說的有個故事要講冠摄,想來想去也不知道怎么起頭糯崎,也不知道為什么要講。十年的好友直接勸我說河泳,別寫了沃呢,寫出來會分...
    ShineNa小紅瓶一時傾閱讀 112評論 0 0