?xml version="1.0" encoding="UTF-8"?
KVC中最常見的異常就是不小心使用了錯誤的Key碌上,或者在設值中不小心傳遞了nil的值
因為KVC傳遞進去的值和取出來的值都是id類型倚评,取值時KVC為結構體和變量類型是值類型的都會被封裝為NSNumber或者NSValue返回回來,但是設置值的時候就需要自己去做這個轉換了馏予,也就是說開發(fā)者需要自己擔保類型的正確性天梧,運行時OC會在發(fā)送消息的時候檢查類型,所以當你給一個非對象傳一個nil進去就會有問題霞丧。
如何避免產生崩潰:
崩潰的原因是找不到對應的key呢岗,很多時候是手寫字符串錯誤,為了避免這種情況,?我們通過@selector()獲取到方法的SEL后豫,然后通過NSStringFromSelector()將SEL反射為字符串悉尾。這樣在@selector()中傳入方法名的過程中,編譯器會有合法性檢查挫酿,如果方法不存在或未實現(xiàn)會報黃色警告构眯。
解決產生的崩潰:
①.當根據(jù)KVC的搜索規(guī)則,沒有搜索到對應的key或者keypath饭豹,會調用下面兩個相對應的異常方法鸵赖,兩個方法的默認實現(xiàn)是拋出異常從而產生的崩潰。解決方法是重寫下邊兩個方法拄衰,一般是打印沒找到的key它褪。
valueForUndefinedKey:
setValue: forUndefinedKey:
②.當通過KVC給某個非對象的屬性賦值為nil時,會調用這個方法翘悉,從而拋出異常茫打。
setNilValueForKey:
實現(xiàn)原理,或者說KVC是怎么尋找key的妖混?
①當調用setValue:forKey:方法的時候:
首先程序會調用set<Key>屬性值方法老赤,也就是先找setter方法。
如果沒有找到制市,KVC會檢查+ (BOOL)accessInstanceVariablesDirectly方法的返回值抬旺,默認返回YES,那么系統(tǒng)會遵循KVC的搜索原則即先去搜索該類里有沒有_<key>命名的變量名祥楣,無論在類的哪里定義开财,也無論什么修飾符,只要存在KVC都可以對其進行賦值误褪。
如果set<Key>和_<key>都沒有找到责鳍,那么再找_is<Key>的成員變量,再沒有兽间,再找<key>和is<Key>的成員變量历葛,找到了賦值。
如果set方法和四種成員變量都沒有嘀略,系統(tǒng)調用setValue:forUNdefinedKey:方法恤溶,默認是拋出異常。
如果+ (BOOL)accessInstanceVariablesDirectly方法的返回NO屎鳍,那么不再去找四種成員變量直接調用setValue:forUNdefinedKey:
②當調用valueForKey:方法的時候:
首先按get<Key>,<key>,is<Key>的順序方法查找getter方法宏娄。
如果上邊的方法里沒有找到,KVC會查找countOf<Key>,objectIn<Key>AtIndex,<Key>AtIndex格式的方法,是否有被實現(xiàn)逮壁,如果這其中countOf<Key>和objectIn<Key>AtIndex,<Key>AtIndex中兩個方法中任一個方法實現(xiàn)了孵坚,那么會返回一個可以響應NSArray所有方法的代理集合類名叫做NSKeyValueArray粮宛。 給這個代理集合發(fā)送NSArray的方法,就會以countOf<Key>,objectIn<Key>AtIndex,<Key>AtIndex就會以這幾個方法的形式返回卖宠。
如果上邊的方法里沒有找到巍杈,KVC會查找countOf<Key>,enumeratorOf<Key>,memberOf<Key>格式的方法,是否有被實現(xiàn)扛伍,如果有這三個方法都被實現(xiàn)筷畦,會返回一個可以響應NSSet所有方法的代理集合。
如果還是沒有找到刺洒,再檢查類方法+ (BOOL)accessInstanceVariablesDirectly,默認返回yes鳖宾,那么和先前的設值一樣,會按_<key>,_is<Key>,<key>,is<Key>的順序搜索成員變量名逆航。返回NO的話鼎文,那么會直接調用valueForUndefinedKey:。
還沒有找到的話因俐,調用valueForUndefinedKey:拇惋。
比如一個類實現(xiàn)了下圖所示的方法,
當調用[obj valueForKey:@“numbers”],的時候抹剩,如果找不到三種get方法撑帖,那么此時會返回一個叫做NSKeyValueArray的類。
當你給這個類發(fā)送NSArray的方法時澳眷,就會調用上邊你所實現(xiàn)的方法胡嘿,比如調用[ar count]就會調用你實現(xiàn)的countOfNumbers方法。調用ar[0],就會調用你實現(xiàn)的objectInNumbersAtIndex:方法钳踊。