《Objective-C基礎(chǔ)教程》讀書筆記15—鍵值編碼

許多編程技術(shù)都基于間接機(jī)制荔仁,包括整個面向?qū)ο缶幊填I(lǐng)域售貌。鍵值編碼也是一種間接機(jī)制育特,這種機(jī)制不屬于Objective-C語言的特性丙号,而是Cocoa提供的一種特性。
我們可以通過直接調(diào)用方法缰冤、屬性的點表示法或設(shè)置實例變量來直接更改對象狀態(tài)犬缨。鍵值編碼是一種間接更改對象狀態(tài)的方式,稱其為KVC棉浸,其實現(xiàn)方法是使用字符串表示要更改的對象狀態(tài)怀薛。
一些更加高級的Cocoa特性,比如CoreData和CocoaBindings迷郑,也在基礎(chǔ)機(jī)制中使用了KVC功能枝恋。
1 入門項目
2 KVC簡介
鍵/值編碼中的基本調(diào)用是 -valueForKey:和-setValue:forKey:方法。你可以向?qū)ο蟀l(fā)送消息嗡害,并傳遞你想要訪問的屬性名稱的鍵作為參數(shù)焚碌。
我們可以通過如下方法訪問對象的屬性:


image.png

image.png

valueForKey:的功能非常強(qiáng)大,它可以找到相關(guān)屬性的值并將其返回霸妹。
valueForKey:會首先查找以參數(shù)名命名(格式為-key或-isKey)的getter方法十电。對于以上前兩個調(diào)用,valueForKey:會先尋找-name和-make方法抑堡。如果沒有這樣的getter方法摆出,它將會在對象內(nèi)尋找名稱格式為_key或key的實例變量。
非常重要的一點:-valueForKey在Objective-C運(yùn)行時中使用元數(shù)據(jù)打開對象并進(jìn)入其中查找需要的信息首妖。在C或C++語言中不能執(zhí)行這種操作偎漫。通過使用KVC,沒有相關(guān)getter方法也能獲取對象值,不需要通過對象指針來直接訪問實例變量有缆。
對于KVC, Cocoa會自動裝箱和開箱標(biāo)量值象踊。也就是說,當(dāng)使用setValueForKey時棚壁,它會自動將標(biāo)量值(int杯矩、float和struct)放入NSNumber或NSValue中;當(dāng)使用-setValueForKey時袖外,它自動將標(biāo)量值從這些對象中取出史隆。僅KVC具有這種自動裝箱功能,常規(guī)方法調(diào)用和屬性語法不具備該功能曼验。
除了檢索值外泌射,還可以使用-setValue:forKey:方法依據(jù)名稱設(shè)置值粘姜。
以上方法的工作方式與-valueForKey:相同。它先查找名稱的setter方法熔酷,然后調(diào)用它并傳遞參數(shù)孤紧。如果不存在setter方法,它將在類中尋找名為key或_key的實例變量拒秘,然后為它賦值号显。
編譯器和蘋果公司都以下劃線開頭的形式保存實例變量名稱,所以躺酒,你最好遵守這條規(guī)則押蚤,不要在其他地方使用下劃線。
如果你想設(shè)置一個標(biāo)量值阴颖,在調(diào)用-setValue:forKey:方法之前需要將它們包裝起來活喊,也就是裝箱到對象中,而對于KVC的賦值方法量愧,Cocoa會自動開箱先取標(biāo)量值钾菊,再賦值。
3.鍵路徑
表示鍵路徑:可以在不同的變量名稱之間用圓點分開偎肃。


image.png

image.png

這些鍵路徑的深度是任意的煞烫,具體取決于對象圖(object graph, 可以表示對象之間的關(guān)系)的復(fù)雜度,可以使用諸如car.interior.airconditioner.fan.velocity這樣的鍵路徑累颂。在某種程度上滞详,使用鍵路徑比使用一系列嵌套方法調(diào)用更容易訪問到對象。
4.整體操作
關(guān)于KVC非常棒的一點是紊馏,如果使用某個鍵值來訪問一個NSArray數(shù)組料饥,它實際上會查詢相應(yīng)數(shù)組中的每個對象,然后將查詢結(jié)果打包到另一個數(shù)組中并返回給你朱监。這種方法也同樣適用于通過鍵路徑訪問的位于對象中的數(shù)組岸啡。
在KVC中,通常認(rèn)為對象的NSArray具有一對多的關(guān)系赫编。如果鍵路徑中含有一個數(shù)組屬性巡蘸,則該路徑的其余部分將被發(fā)送給數(shù)組中的每個對象。(第二句話后一部分的理解: NSArray數(shù)組實現(xiàn)valueForKeyPath:的方法是循環(huán)遍歷它的內(nèi)容并向每個對象發(fā)送消息擂送。因此NSArray向每個在自身之中的對象發(fā)送了參數(shù)以剩余部分作為鍵路徑的valueForKeyPath:消息悦荒,結(jié)果就將數(shù)組中每個對象對應(yīng)的屬性值放到數(shù)組中返回)。
鍵路徑的缺點: 不幸的是嘹吨,不能在鍵路徑中索引對象的數(shù)組搬味,比如說獲取對象的數(shù)組中的第一個被包含對象的屬性值。
一對一關(guān)系,一般對象的復(fù)合都是一對一關(guān)系身腻。
4.1 休息一下
懶加載也可以稱之為惰性初始化产还,僅在需要時才去創(chuàng)建它匹厘。這是編程技術(shù)的一種思想嘀趟。

4.2 快速運(yùn)算
鍵路徑不僅能引用對象值,還可以引用一些運(yùn)算符來進(jìn)行一些運(yùn)算愈诚,例如能獲取一組值的平均值或返回這組值中的最小值和最大值她按。


image.png

image.png

注意:上述代碼中的@count, 其中@符號意味著后面將進(jìn)行一些運(yùn)算。對編譯器來說炕柔,@"blah"是一個字符串酌泰,而@interface用于聲明類。此處的@count用于通知KVC機(jī)制計算鍵路徑左側(cè)值的對象總數(shù)匕累。而@sum陵刹、@avg、@min欢嘿、@max衰琐、@distinctUnionOfObjects等運(yùn)算符將鍵路徑分成兩部分。第一部分可以看成一對多關(guān)系的鍵路徑炼蹦,另一部分可以看成任何包含一對多關(guān)系的鍵路徑羡宙。它被當(dāng)作用于關(guān)系中每個對象的鍵路徑。(獲取左側(cè)指定的集合掐隐,對該集合中的每個對象使用右側(cè)的鍵路徑狗热,然后將結(jié)果轉(zhuǎn)換為一個集合。名稱中的union指一組對象的并集虑省,distince用于刪除重復(fù)內(nèi)容匿刮。KVC還支持多種運(yùn)算符,可供自己探索探颈,不過遺憾的是熟丸,你無法添加自己的運(yùn)算符。
KVC的功能非常強(qiáng)大膝擂,可以非常輕松地處理集合類虑啤,似乎完全可以取代對象的存取方法和其他代碼編寫。但是KVC有以下兩個缺點:
① KVC需要解析字符串來計算你需要的答案架馋,因此速度比較慢狞山。
② 編譯器無法對鍵路徑進(jìn)行錯誤檢查。當(dāng)你嘗試使用它時叉寂,一旦出現(xiàn)鍵路徑錯誤萍启,程序直接crash掉。
個人意見:一般情況下,通過對象的存取方法和其他代碼實現(xiàn)不了相應(yīng)的功能時勘纯,再考慮使用KVC局服。
  1. 批處理
    KVC包含兩個調(diào)用, 一個可以批量獲取,另一個可以批量更改驳遵。


    image.png

    image.png

    注意:集合類對象中不能包含nil值淫奔,因為nil是集合類對象的終止符號,若包含堤结,則會引起非法參數(shù)異常程序crash唆迁。在OC中,我們一般使用[NSNull null]表示nil值竞穷。

  2. nil仍然可用
    雖然nil不可在集合類對象中使用唐责,但仍然可在KVC賦值中使用,而對于屬性標(biāo)量值設(shè)置為nil程序crash的問題有辦法解決瘾带。


    image.png

    image.png

    注意:如果得到了一個意外之料的鍵鼠哥,我們可以調(diào)用超類方法。
    一般來說看政,除非你有某些特殊的原因朴恳,比如不想執(zhí)行某個操作,否則應(yīng)該總是在重寫的代碼中調(diào)用超類的方法帽衙。

  3. 處理未定義的鍵
    使用KVC菜皂,處理未定義的鍵,需要重寫相關(guān)的方法厉萝。如果KVC機(jī)制無法找到處理方式恍飘,會退回并詢問該類如何處理。默認(rèn)的實現(xiàn)會取消操作谴垫,但是我們可以更改默認(rèn)的行為章母。


    image.png

    image.png

    image.png

    注意:
    ① <null>為后端返回數(shù)據(jù),或者控制臺打印翩剪,<null>是一種[NSNull null]對象乳怎。所以,當(dāng)服務(wù)端返回<null>前弯,前端可用[NSNull null]來進(jìn)行判斷蚪缀;(null) 是一個真正的nil值,所以恕出,同樣询枚,移動端可用nil值來判斷服務(wù)端端返回的(null)。
    ② 對于字典浙巫,使用KVC的賦值方法(setValue:forKey:)金蜀,調(diào)用者可以直接傳入nil值刷后。而如果為字典的setObject:forKey:提供nil值,它將會給出警告信息渊抄,程序crash尝胆。其實,對于后臺返回的數(shù)據(jù)或者用戶輸入的數(shù)據(jù)护桦,在提交字典參數(shù)請求服務(wù)端時都必須進(jìn)行非空判斷含衔,最好的辦法是在程序中每一處進(jìn)行非空判斷,另外一種辦法:可以嘗試使用runtime解決嘶炭。
    ③ 如果在字典中對setValue:forKey:方法傳入nil值抱慌,可能會把對應(yīng)鍵的值從字典中刪除。但即使這樣眨猎,在kvc中,nil值仍然可用强经。
    小結(jié):
    ① KVC通過查找setter和getter方法來使用單個鍵設(shè)置值或者獲取值睡陪。如果KVC無法找到任何方法,將直接進(jìn)入對象并更改值匿情。
    ② 鍵路徑:它們是由點分割的鍵兰迫,用于在對象的網(wǎng)絡(luò)中指定路徑。也許這些鍵路徑看起來很像訪問屬性炬称,但實際上它們是兩種完全不同的機(jī)制汁果。可以將各種運(yùn)算符嵌入到鍵路徑中玲躯,以使KVC實現(xiàn)其他功能据德。
    ③ 通過重寫系統(tǒng)方法可以定制個別行為。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末跷车,一起剝皮案震驚了整個濱河市棘利,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌朽缴,老刑警劉巖善玫,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異密强,居然都是意外死亡茅郎,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門或渤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來系冗,“玉大人,你說我怎么就攤上這事劳坑”锨矗” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長涝开。 經(jīng)常有香客問我循帐,道長,這世上最難降的妖魔是什么舀武? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任拄养,我火速辦了婚禮,結(jié)果婚禮上银舱,老公的妹妹穿的比我還像新娘瘪匿。我一直安慰自己,他們只是感情好寻馏,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布棋弥。 她就那樣靜靜地躺著,像睡著了一般诚欠。 火紅的嫁衣襯著肌膚如雪顽染。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天轰绵,我揣著相機(jī)與錄音粉寞,去河邊找鬼。 笑死左腔,一個胖子當(dāng)著我的面吹牛唧垦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播液样,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼振亮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蓄愁?” 一聲冷哼從身側(cè)響起双炕,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎撮抓,沒想到半個月后妇斤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡丹拯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年站超,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乖酬。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡死相,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出咬像,到底是詐尸還是另有隱情算撮,我是刑警寧澤生宛,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站肮柜,受9級特大地震影響陷舅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜审洞,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一莱睁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧芒澜,春花似錦仰剿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至阅酪,卻和暖如春旨袒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背术辐。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留施无,地道東北人辉词。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像猾骡,于是被迫代替她去往敵國和親瑞躺。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

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

  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時...
    歐辰_OSR閱讀 29,334評論 8 265
  • KVC KVC定義 KVC(Key-value coding)鍵值編碼兴想,就是指iOS的開發(fā)中幢哨,可以允許開發(fā)者通過K...
    暮年古稀ZC閱讀 2,132評論 2 9
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,090評論 1 32
  • 源碼加翻譯 #import <Foundation/NSArray.h> #import <Foundation/...
    CAICAI0閱讀 1,148評論 0 50
  • 關(guān)于鍵值編碼 鍵值編碼(KVC)是一種由NSKeyValueCoding非正式協(xié)議提供的機(jī)制,對象采用該機(jī)制來提供...
    漸z閱讀 913評論 0 0