KVC的底層原理,使用和自定義KVC

Kvc簡(jiǎn)介:

KVC(Key-value coding)鍵值編碼温亲,顧名思義栈虚。額史隆,簡(jiǎn)單來(lái)說(shuō),是可以通過(guò)對(duì)象屬性名稱(Key)直接給屬性值(value)編碼(coding)“編碼”可以理解為“賦值”粘姜。這樣可以免去我們調(diào)用getter和setter方法相艇,從而簡(jiǎn)化我們的代碼纯陨,也可以用來(lái)修改系統(tǒng)控件內(nèi)部屬性(這個(gè)黑魔法且用且珍惜)测柠。

舉例:


image.png

如果不使用kvc我們正常使用是:


image.png

使用kvc的話是:


image.png

上面介紹了基本的kvc使用方法获讳,下面我們來(lái)學(xué)習(xí)一下他的原理:

kvc取值的底層原理

引入:
假如我們使用kvc取值丐膝,


image.png

這時(shí)候運(yùn)行的話肯定會(huì)報(bào)錯(cuò),回報(bào)未定義的崩潰錯(cuò)誤偎肃,那么我們接下來(lái)學(xué)習(xí)kvc他是怎么找的:
比如我們的


image.png

1》我們kvc在底層可不是僅僅找name這個(gè)key累颂,他一共會(huì)找四個(gè)key,四個(gè)key的分別是:
_name _isName name isName
這四個(gè)key的優(yōu)先級(jí)是從高到低依次是_name _isName name isName

如果這四個(gè)都沒(méi)有那么就會(huì)遇到上面說(shuō)的崩潰報(bào)錯(cuò)了
2》你以為到這里就結(jié)束了嗎料饥?
其實(shí)這個(gè)valueForKey:方法 不止找這幾個(gè)成員變量朱监,他還會(huì)找下面這個(gè)方法:


image.png

如果返回值是YES,他才去找那四個(gè)成員變量赫编,如果是NO的話就不會(huì)去找那四個(gè)成員變量(即使定義的有),直接崩潰錯(cuò)誤赡若。
3》 你以為到這里又結(jié)束了嗎团甲?
這個(gè)valueForKey:方法其實(shí)還會(huì)找其他東西的,拿他去找什么的身腻,他其實(shí)還會(huì)找getter方法(getter是個(gè)復(fù)數(shù))匹厘,會(huì)找那些get方法呢,如下:
image.png

這三個(gè)方法的優(yōu)先級(jí)是:name她按,isName炕柔,getName
4》到此還沒(méi)有完,他還會(huì)找兩個(gè)方法陵刹,如下:
image.png

如果他找了這兩個(gè)方法衰琐,會(huì)輸出什么呢炼蹦,會(huì)輸出個(gè)數(shù)組,這個(gè)數(shù)組里面是10個(gè)字符串“haha”
5》辛辨,上面的還不完整,其實(shí)還可能會(huì)走一個(gè)方法指攒。
即如果走到了2》僻焚,但是2》返回值為no,就自己餓會(huì)崩潰隙弛,如果我們不想崩潰的話狞山,就重寫這個(gè)方法
image.png

至此算是全部結(jié)束,你會(huì)疑問(wèn)1》 2》 3》 4》這么多kvc都要去找总珠,那么具體順序是什么呢勘纯?下面我們來(lái)總結(jié)一下這個(gè)具體順序

關(guān)于KVC valueForKey:key 的調(diào)用查找順序
|-先調(diào)用“相關(guān)”方法,先后順序是:
1》|-getter方法淫奔,getKey -> key -> isKey (注意字母大小寫)
2》|- NSArray方法:countOfKey 和objectInKeyAtIndex
|-如果沒(méi)有相關(guān)方法堤结,會(huì)找2》也就是看+(BOOL)accessInstanceVariablesDirectly 返回值
1 》 |-YES 的話去找成員變量1》,順序依次是_key -> _isKey -> key -> isKey
2 》 |-NO 的話就直接拋崩潰異常了媒惕。但是蘋果還給了我們一個(gè)救火的方法来庭,如果這個(gè)返回值是no月弛,但是我們還不想崩潰怎么辦科盛,我們就只能重寫valueForUndefinedKey,返回值為nil,這樣就不會(huì)崩潰了

OK厉萝,到這里我們總結(jié)了關(guān)于kvc取值查找的過(guò)程,算了還是在用語(yǔ)言描述一下加深下印象吧章母,

文字總結(jié):我們通過(guò)kvc的valueForKey:key方法去取值的時(shí)候翩剪,首先我們回去找getter的那三個(gè)方法,找到的話按照優(yōu)先級(jí)得到值蚪缀,如果三個(gè)getter方法沒(méi)有話的恕出,kvc會(huì)繼續(xù)找NSArray方法,就是countOfKey 和objectInKeyAtIndex 他們兩個(gè)金蜀,如果有的話就返回個(gè)數(shù)組狈醉。如果這兩個(gè)NSArray方法也沒(méi)有的話,我們會(huì)繼續(xù)去找抒线,繼續(xù)去找+(BOOL)accessInstanceVariablesDirectly這個(gè)返回值為bool類型的方法渣慕,如果他的返回值是yes,那么我們就去找哪四個(gè)成員變量眨猎,也是按照優(yōu)先級(jí)取值;如果+(BOOL)accessInstanceVariablesDirectly這個(gè)返回值為no的話睡陪,就不去找那四個(gè)成員變量了匿情,回去找看有沒(méi)有重載valueForUndefinedKey這個(gè)方法,按照要求重載了的話不會(huì)崩潰汁果,kvc這個(gè)valueForKey:key會(huì)得到一個(gè)null值玲躯,如果沒(méi)有重載這個(gè)方法鳄乏,那么就會(huì)直接崩潰

ps:對(duì)于valueForKeyPath:path,這種點(diǎn)點(diǎn)點(diǎn)下去的路徑key橱野,和其他的原理一樣


kvc設(shè)值的底層原理

[model setValue:@"kvcName" forKeyPath:@"name"];
通過(guò)我們上面kvc的取值的學(xué)習(xí)赡译,這里kvc的設(shè)值也是需要找的,那她找的順序是什么呢裹唆?

  1. 1.setter相關(guān)方法


    image.png

    setter的方法就這兩個(gè)许帐,他們的優(yōu)先級(jí)為setName -> setIsName

  2. 找成員變量_name -> _isName -> name -> isName
  3. 和取值一樣也要看+(BOOL)accessInstanceVariablesDirectly這個(gè)方法的返回值
  4. 去取值一樣也有個(gè)救火的方法:


    image.png
  5. 如果我們給一個(gè)基本數(shù)據(jù)類型通過(guò)kvc設(shè)值毕谴,value給了一個(gè)nil,那么直接就會(huì)崩了循帐,所以還有個(gè)異常處理方法來(lái)防治這個(gè)崩潰


    image.png

至此kvc的設(shè)值就結(jié)束了拄养,我們來(lái)總結(jié)一下他的過(guò)程

  1. 尋找setter的兩個(gè)方法
  2. 如果setter的兩個(gè)方法都沒(méi)有银舱,看+(BOOL)accessInstanceVariablesDirectly這個(gè)方法的返回值方法的返回值

YES 去找四個(gè)成員變量
NO 去找valueForUndefinedKey,有的話不會(huì)崩潰寻馏,沒(méi)有的話會(huì)崩潰

  1. 對(duì)于基本數(shù)據(jù)類型的setValue:value forKey:key,如果value為nil的話他會(huì)直接崩潰,所以kvc在基本數(shù)據(jù)類型value為nil的時(shí)候還回去找setNilValueForKey這個(gè)方法是否重載實(shí)現(xiàn)了顽染,如果重載了就不會(huì)崩潰轰绵,否則會(huì)崩潰

自定義一個(gè)kvc, 不使用系統(tǒng)的kvc

  1. 首先我們想一下系統(tǒng)的kvc是不是任何類都可以使用,所以系統(tǒng)的kvc是不是肯定是寫在NSObject的分類里面呢耀找,所以我們自定的話就先新建一個(gè)NSObject的分類

  2. 我們自定義取值和設(shè)值的方法


    image.png
  3. 來(lái)實(shí)現(xiàn)這兩個(gè)方法,先看實(shí)現(xiàn)set的方法


    image.png

    image.png

    image.png

    image.png

    寫的時(shí)候可以自己通過(guò)自定的Person類和vc中測(cè)試一下
    下面是自己測(cè)試的部分代碼:


    image.png

    image.png

    image.png

自己自定義的kvc設(shè)置值的方法,其實(shí)也就是按照上面學(xué)的邏輯來(lái)寫的妇斤,kvc取值的就不在寫了丹拯,比較簡(jiǎn)單,就不在這里重復(fù)了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末死相,一起剝皮案震驚了整個(gè)濱河市咬像,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌肮柜,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件审洞,死亡現(xiàn)場(chǎng)離奇詭異预明,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)撰糠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門阅酪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人术辐,你說(shuō)我怎么就攤上這事施无。” “怎么了猾骡?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)幢哨。 經(jīng)常有香客問(wèn)我,道長(zhǎng)捞镰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任践樱,我火速辦了婚禮冰评,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘解孙。我一直安慰自己,他們只是感情好弛姜,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布妖枚。 她就那樣靜靜地躺著,像睡著了一般荠商。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上莱没,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天饰躲,我揣著相機(jī)與錄音,去河邊找鬼嘹裂。 笑死摔握,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的氨淌。 我是一名探鬼主播狡逢,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蛮艰!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起壤蚜,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤袜刷,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后著蟹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奸披,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年涮雷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片样刷。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡览爵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拾枣,到底是詐尸還是另有隱情,我是刑警寧澤司蔬,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布姨蝴,位于F島的核電站,受9級(jí)特大地震影響左医,放射性物質(zhì)發(fā)生泄漏同木。R本人自食惡果不足惜跛十,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望洲尊。 院中可真熱鬧,春花似錦坞嘀、人聲如沸惊来。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至昆淡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間昂灵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工眨补, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留倒脓,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓甘晤,卻偏偏與公主長(zhǎng)得像饲做,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子盆均,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359