iOS底層原理 -- KVO的本質(zhì)

使用方式

通過(guò)以下例子來(lái)總結(jié)使用方式

// ViewController.h
#import "ViewController.h"
#import "Person.h"

@interface ViewController ()
@property (nonatomic, strong) Person *person;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    Person *person = [[Person alloc] init];
    self.person = person;
    person.age = 10;
    person.age = 20;
    
    // 添加觀察者為當(dāng)前控制器砾省,對(duì)age進(jìn)行觀察
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew;
    [person addObserver:self forKeyPath:@"age" options:options context:nil];
    
    person.age = 30;
}

- (void)dealloc {
    // 移除觀察者,防止內(nèi)存泄露
    [self.person removeObserver:self forKeyPath:@"age"];
}

// 當(dāng)被觀察的數(shù)據(jù)變化時(shí)沸手,提醒觀察者
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    NSLog(@"改變的值---- %@", change);
    
}


@end

result: 
改變的值---- {
    kind = 1;
    new = 30;
    old = 20;
}

使用方式:
1内边、添加觀察者

- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;

2、觀察者實(shí)現(xiàn)對(duì)應(yīng)的觀察方法(數(shù)據(jù)變化時(shí)進(jìn)行處理)

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)contex

3索绪、移除觀察者(防止內(nèi)存泄露)

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

本質(zhì)分析

原來(lái)上面的例子Person中person.age = 10湖员、person.age = 20與person.age = 30在寫(xiě)法上沒(méi)有任何區(qū)別,都是調(diào)用了setter方法瑞驱。而唯有添加了觀察者后的娘摔,person.age = 30才有反應(yīng)。
從編譯時(shí)看不出來(lái)變化唤反,說(shuō)明在KVP是在runtime時(shí)動(dòng)了手腳凳寺。
在添加觀察者前后分別打斷點(diǎn),可以看到isa指針變化了彤侍。

添加觀察者前.png
添加觀察后.png

實(shí)際上加了KVO后肠缨,對(duì)象的isa指針會(huì)重新指向 “NSKVONotifying_對(duì)象” (實(shí)際上市該類(lèi)對(duì)象的子類(lèi))
而在 “NSKVONotifying_對(duì)象”該類(lèi)對(duì)象中 重新了setter方法。
重寫(xiě)方法中實(shí)際調(diào)用過(guò)程為

[self willChangeValueForKey:@"age"];
[super setAge:age];
[self didChangeValueForKey:@"age"];

而在didChangeValueForKey:方法中盏阶,會(huì)調(diào)用觀察者的觀察方法即[obser observeValueForKeyPath:@"age" ofObject:self change:{} content:nil];

為了證明這個(gè)過(guò)程晒奕,操作如下
Person.m文件中以下方法

// Person.m
- (void)willChangeValueForKey:(NSString *)key {
    NSLog(@"%s", __func__);
    [super willChangeValueForKey:key];
}

- (void)setAge:(int)age {
    NSLog(@"%s", __func__);
    _age = age;
}

- (void)didChangeValueForKey:(NSString *)key {
    NSLog(@"%s",  __func__);
    [super didChangeValueForKey:key];
    NSLog(@"%s", __func__);
}

ViewController.m文件中以下方法

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

打印結(jié)果如下

-[Person setAge:]
-[Person setAge:]
// KVO 的過(guò)程
-[Person willChangeValueForKey:]
-[Person setAge:]
-[Person didChangeValueForKey:]
-[ViewController observeValueForKeyPath:ofObject:change:context:]
-[Person didChangeValueForKey:]

上述表明KVO調(diào)用過(guò)程實(shí)際就是

[self willChangeValueForKey:@"觀察的值"];
[super setAge:值];
[self didChangeValueForKey:@"觀察的值"];

而在didChangeValueForKey:中又調(diào)用了觀察者的觀察方法即observeValueForKeyPath:ofObject:change:context方法。

問(wèn)題

1名斟、KVO本質(zhì)是什么脑慧?
本質(zhì)是改變了對(duì)象isa指針的指向并重寫(xiě)了setter方法,指向一個(gè)NSKVONotifying_對(duì)象的子類(lèi)對(duì)象砰盐。
重寫(xiě)setter方法闷袒,如下
1)willChangeValueForKey:
2)父類(lèi)原來(lái)的setter
3)didChangeValueForKey:
內(nèi)部會(huì)觸發(fā)觀察者(Oberser)的觀察方法( observeValueForKeyPath:ofObject:change:context:)

2、如何手動(dòng)觸發(fā)KVO岩梳?
手動(dòng)調(diào)用調(diào)用willChangeValueForKey:和didChangeValueForKey:方法囊骤。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蒋腮,隨后出現(xiàn)的幾起案子淘捡,更是在濱河造成了極大的恐慌,老刑警劉巖池摧,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焦除,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡作彤,警方通過(guò)查閱死者的電腦和手機(jī)膘魄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)乌逐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人创葡,你說(shuō)我怎么就攤上這事浙踢。” “怎么了灿渴?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵洛波,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我骚露,道長(zhǎng)蹬挤,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任棘幸,我火速辦了婚禮焰扳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘误续。我一直安慰自己吨悍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布蹋嵌。 她就那樣靜靜地躺著育瓜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪栽烂。 梳的紋絲不亂的頭發(fā)上爆雹,一...
    開(kāi)封第一講書(shū)人閱讀 51,718評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音愕鼓,去河邊找鬼。 笑死慧起,一個(gè)胖子當(dāng)著我的面吹牛菇晃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蚓挤,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼磺送,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了灿意?” 一聲冷哼從身側(cè)響起估灿,我...
    開(kāi)封第一講書(shū)人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缤剧,沒(méi)想到半個(gè)月后馅袁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡荒辕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年汗销,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了犹褒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弛针,死狀恐怖叠骑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情削茁,我是刑警寧澤宙枷,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站茧跋,受9級(jí)特大地震影響慰丛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜厌衔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一璧帝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧富寿,春花似錦睬隶、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至变勇,卻和暖如春恤左,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背搀绣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工飞袋, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人链患。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓巧鸭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親麻捻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子纲仍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

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

  • 問(wèn)題 iOS用什么方式實(shí)現(xiàn)對(duì)一個(gè)對(duì)象的KVO?(KVO的本質(zhì)是什么贸毕?) 如何手動(dòng)觸發(fā)KVO 郑叠? 首先需要了解KVO...
    hjltony閱讀 579評(píng)論 0 2
  • 面試問(wèn)題: · iOS用什么方式實(shí)現(xiàn)對(duì)一個(gè)對(duì)象的KVO? · 如何手動(dòng)觸發(fā)KVO明棍? 我們通過(guò)以下幾個(gè)點(diǎn)來(lái)尋找這兩個(gè)...
    高思陽(yáng)閱讀 239評(píng)論 0 1
  • KVC KVC定義 KVC(Key-value coding)鍵值編碼乡革,就是指iOS的開(kāi)發(fā)中,可以允許開(kāi)發(fā)者通過(guò)K...
    暮年古稀ZC閱讀 2,147評(píng)論 2 9
  • 對(duì)小碼哥底層班視頻學(xué)習(xí)的總結(jié)與記錄。面試題部分署拟,通過(guò)對(duì)面試題的分析探索問(wèn)題的本質(zhì)內(nèi)容婉宰。 問(wèn)題iOS用什么方式實(shí)現(xiàn)對(duì)...
    xx_cc閱讀 10,781評(píng)論 26 65
  • 一、KVO 的使用 KVO 的全稱(chēng) Key-Value Observing推穷,俗稱(chēng)“鍵值監(jiān)聽(tīng)”心包,可以用于監(jiān)聽(tīng)某個(gè)對(duì)象...
    666真666閱讀 674評(píng)論 0 1