iOS KVO 原理解析 KVC 原理解析

老掉牙的題目了如捅,只是為了總結(jié)下知識(shí)點(diǎn)地淀,還有新進(jìn)門的iOS。不喜勿噴臼寄!


KVO 前言:

我們知道iOS中NSObject對(duì)象可以增加觀察者來(lái)監(jiān)聽(tīng)對(duì)象屬相值得變化霸奕。

1.那么KVO的本質(zhì)是什么呢??

2. KVO可以手動(dòng)觸發(fā)么吉拳?

下面我們就來(lái)看下KVO的實(shí)現(xiàn)

KVO之后的變化

從上圖我們可以看出质帅,當(dāng)實(shí)現(xiàn)KVO之后,p1的isa指針指向的發(fā)生了改變留攒,指向了一個(gè)NSKVONotifying_JWPerson,那么這個(gè)類是從哪來(lái)的呢煤惩?

其實(shí)呢,KVO的本質(zhì)就是:當(dāng)使用KVO之后炼邀,iOS系統(tǒng)會(huì)修改這個(gè)對(duì)象的isa指針魄揉,改為指向一個(gè)全新通過(guò)Runtime動(dòng)態(tài)創(chuàng)建的子類,子類擁有自己的set方法實(shí)現(xiàn)拭宁,內(nèi)部會(huì)調(diào)用willChangeValueForKey 洛退、 原來(lái)的set方法 、 didChangeValueForKey(這個(gè)方法內(nèi)部會(huì)調(diào)用監(jiān)聽(tīng)器的監(jiān)聽(tīng)方法)來(lái)實(shí)現(xiàn)監(jiān)聽(tīng)的目的的杰标。

下面我們就用來(lái)代碼來(lái)大概還原下KVO的過(guò)程:


KVO偽代碼

這就是KVO的本質(zhì)工作原理兵怯。其實(shí)并不是很難,有很容易理解腔剂。下面我們?cè)趤?lái)證實(shí)下我們所說(shuō)的對(duì)不對(duì)媒区。


打印方法

從上圖中我們可以看出,其實(shí)實(shí)現(xiàn)監(jiān)聽(tīng)之后,setAge方法并不是走向原來(lái)的父類的setAge方法袜漩,而是走了_NSSETIntVAalueNotify這個(gè)方法绪爸。。這個(gè)方法是一個(gè)底層的C語(yǔ)言方法宙攻,里面調(diào)用了

willChangeValueForKey:

[super setAge:]

didChangeValueForKey: 在此處調(diào)用[observerobserveValueForKeyPath:@"age" ofObject:(object change:change context:context];l來(lái)進(jìn)行回調(diào)奠货,達(dá)到監(jiān)聽(tīng)值發(fā)生改變的原理。


還有一個(gè)就是:Runtime動(dòng)態(tài)生成的子類粘优,只是重寫(xiě)了setter方法么仇味?答案顯然并不是呻顽,那他都有哪些方法呢雹顺?

方法列表


從圖中我們可以看出NSKVONotifying_JWPerson 一共有四個(gè)方法,一個(gè)是set方法廊遍,一個(gè)是class嬉愧、delloc、_isKVOA? 喉前,下面我們來(lái)說(shuō)下這四個(gè)方法:

1.setter方法不多說(shuō)了没酣,上面已經(jīng)介紹了。

2.class方法的作用是什么呢卵迂?答案就是:當(dāng)我們調(diào)用[object class]方法的時(shí)候裕便,如果子類沒(méi)有改方法,就會(huì)從父類中尋找见咒,直至找到NSObject中的class方法偿衰,進(jìn)行調(diào)用。而NSObject的class實(shí)現(xiàn)是返回 objc_getclass(self)? 實(shí)現(xiàn)的改览,也就是說(shuō)會(huì)直接返回自身類下翎,到那時(shí)apple并不想讓NSKVONotifying_JWPerson給暴露出來(lái),所以重寫(xiě)class方法宝当,進(jìn)而返回你添加觀察者的類视事。

3.delloc方法,是釋放一些資源庆揩。

4.isKVOA 方法俐东,我也不是很懂,有知道的同學(xué)订晌,請(qǐng)留言犬性。。我猜想應(yīng)該是標(biāo)識(shí)是否是KVO的一種狀態(tài)使用的腾仅。



如何手動(dòng)執(zhí)行KVO呢乒裆?我們知道當(dāng)值發(fā)生改變會(huì)觸發(fā)觀察者的方法調(diào)用,但是如何在我們不改變值得情況下觸發(fā)改方法呢?

-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context ;

答案就是 需要手動(dòng)觸發(fā)的話 你需要將

[obj willChangeValueForKey:@"age"];

[obj didChangeValueForKey:@"age"];

這兩行代碼放置執(zhí)行處鹤耍,就會(huì)觸發(fā)觀察者的方法肉迫。這也說(shuō)明了,觸發(fā)KVO回調(diào)的就是通過(guò)這兩個(gè)方法來(lái)實(shí)現(xiàn)的稿黄。


補(bǔ)充:

1.修改實(shí)例的成員變量會(huì)觸發(fā)KVO么喊衫?

? ? 不會(huì)的,KVO是通過(guò)重寫(xiě)setter方法來(lái)進(jìn)行監(jiān)聽(tīng)值得改變杆怕,成員變量賦值是不會(huì)觸發(fā)setter方法族购,因此也并不會(huì)觸發(fā)KVO。



KVC 前言:

鍵值編碼陵珍,通過(guò)setValue賦值的操作修改對(duì)象屬性的值寝杖。那么KVC的原理又是什么樣子的呢?下面我們就來(lái)揭曉一下。

賦值過(guò)程:???當(dāng)操作setValue 的時(shí)候會(huì)尋找 setKey 和 _setKey 依次尋找兩個(gè)方法的實(shí)現(xiàn)互纯,如果實(shí)現(xiàn)瑟幕,則賦值成功,如果沒(méi)有首先會(huì)判斷類方法accessInstanceVariablesDirectly 返回值(默認(rèn)返回YES)留潦,返回NO只盹,直接拋出異常,返回YES則會(huì)依次訪問(wèn)該類的成員變量里面的 _key 兔院、__isKey殖卑、Key、isKey 是否存在,如果四個(gè)成員變量都不存在坊萝,爆出異常孵稽,存在賦值成功。

賦值過(guò)程

取值過(guò)程:當(dāng)操作valueForKey 的時(shí)候會(huì)尋找 getKey 和 key屹堰、isKey肛冶、_key 依次尋找四個(gè)方法的實(shí)現(xiàn),如果實(shí)現(xiàn)扯键,則取值成功睦袖,如果沒(méi)有首先會(huì)判斷類方法accessInstanceVariablesDirectly 返回值(默認(rèn)返回YES),返回NO荣刑,直接拋出異常馅笙,返回YES則會(huì)依次訪問(wèn)該類的成員變量里面的 _key 、__isKey厉亏、Key董习、isKey 是否存在,如果四個(gè)成員變量都不存在,拋出異常爱只,存在取值成功皿淋。

取值過(guò)程


小知識(shí)點(diǎn):

1、[obj setValue:value forKey:@"key"]; 跟?[obj setValue:value forKeyPath:@"key"];的區(qū)別在于:

兩者的區(qū)別在于,forKeyPath更加強(qiáng)大窝趣,可以訪問(wèn)對(duì)象內(nèi)的對(duì)象的屬性疯暑,比如super.son.property,而forKey只能訪問(wèn)當(dāng)前類的屬性。

2哑舒、KVC改變的賦值會(huì)出發(fā)KVO么妇拯?

會(huì)觸發(fā)KVO的,這里觸發(fā)分兩種情況:

當(dāng)key存在setter方法的時(shí)候洗鸵,會(huì)進(jìn)行KVO的監(jiān)聽(tīng)越锈,重寫(xiě)setter方法,進(jìn)行觸發(fā)KVO膘滨。

當(dāng)key不存在setter方法的時(shí)候甘凭,只有成員變量存在的時(shí)候,也會(huì)觸發(fā)KVO監(jiān)聽(tīng)吏祸,是因?yàn)镵VC內(nèi)部調(diào)用了KVO得 willchangeForKey 和didChangeForKey方法來(lái)觸發(fā)KVO对蒲。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末钩蚊,一起剝皮案震驚了整個(gè)濱河市贡翘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌砰逻,老刑警劉巖鸣驱,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蝠咆,居然都是意外死亡踊东,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門刚操,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)闸翅,“玉大人,你說(shuō)我怎么就攤上這事菊霜〖峒剑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我疾呻,道長(zhǎng)溉委,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任浪讳,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘滑凉。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布畅姊。 她就那樣靜靜地躺著闪幽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涡匀。 梳的紋絲不亂的頭發(fā)上盯腌,一...
    開(kāi)封第一講書(shū)人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音陨瘩,去河邊找鬼腕够。 笑死,一個(gè)胖子當(dāng)著我的面吹牛舌劳,可吹牛的內(nèi)容都是我干的帚湘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼甚淡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼大诸!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起贯卦,我...
    開(kāi)封第一講書(shū)人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤资柔,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后撵割,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體贿堰,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年啡彬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了羹与。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡庶灿,死狀恐怖纵搁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情往踢,我是刑警寧澤腾誉,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站菲语,受9級(jí)特大地震影響妄辩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜山上,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一眼耀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧佩憾,春花似錦哮伟、人聲如沸干花。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)池凄。三九已至,卻和暖如春鬼廓,著一層夾襖步出監(jiān)牢的瞬間肿仑,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工碎税, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尤慰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓雷蹂,卻偏偏與公主長(zhǎng)得像伟端,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子匪煌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉责蝠,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,726評(píng)論 0 9
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,417評(píng)論 8 265
  • 一、概述 KVO萎庭,即:Key-Value Observing霜医,它提供一種機(jī)制,當(dāng)指定的對(duì)象的屬性被修改后擎椰,則其觀察...
    DeerRun閱讀 10,084評(píng)論 11 33
  • 該文章屬于劉小壯原創(chuàng)支子,轉(zhuǎn)載請(qǐng)注明:劉小壯[http://www.reibang.com/u/2de707c93d...
    劉小壯閱讀 48,499評(píng)論 35 227
  • 一创肥、什么是KVO KVO和Notification是Objective-C語(yǔ)言中觀察者模式的兩種實(shí)現(xiàn)機(jī)制达舒。KVO指...
    坤坤同學(xué)閱讀 286評(píng)論 0 0