KVC
?KVC是Key-Value Coding
的簡稱,稱爲鍵值編碼
。它是NSKeyValueCoding
非正式協議啓用的一種機制,可使對象經過該協議來間接訪問其屬性
,這種間接訪問機制補充了實例變量及其相關的訪問器方法所提供的直接訪問。html
//經過setValue中key來設值
- (void)setValue:(nullable id)value forKey:(NSString *)key;
//經過valueForKey中key來取值
- (nullable id)valueForKey:(NSString *)key;
//經過valueForKeyPath中keyPath來設置值
- (nullable id)valueForKeyPath:(NSString *)keyPath;
//keyPath來取值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
複製代碼
效果以下markdown
//默認返回YES,表示若是沒有找到Set<Key>方法的話,會按照_key,_iskey,key,iskey的順序搜索成員,設置成NO就不這樣搜索
+ (BOOL)accessInstanceVariablesDirectly;
//KVC提供屬性值正確性驗證的API,它能夠用來檢查set的值是否正確、爲不正確的值作一個替換值或者拒絕設置新值並返回錯誤緣由。
- (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
//這是集合操做的API,裏面還有一系列這樣的API,若是屬性是一個NSMutableArray,那麼能夠用這個方法來返回。
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;
//若是Key不存在,且KVC沒法搜索到任何和Key有關的字段或者屬性,則會調用這個方法,默認是拋出異常。
- (nullable id)valueForUndefinedKey:(NSString *)key;
//和上一個方法同樣,但這個方法是設值。
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
//若是你在SetValue方法時面給Value傳nil,則會調用這個方法
- (void)setNilValueForKey:(NSString *)key;
//輸入一組key,返回該組key對應的Value,再轉成字典返回,用於將Model轉到字典。
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
複製代碼
上面咱們講到了KVC
一些常見的API,那麼在設置值以及取值
中,iOS底層到底作了什麼呢?從代碼上咱們看到這些API
是Foundation
框架下的,因爲Foundation
是不開源的,所以咱們沒法經過源碼查看底層到底是如何實現的。可是咱們能夠經過蘋果官方文檔
來查看。查看蘋果相關文檔 Key-Value Coding Programming Guideapp
咱們從官方文檔中能夠得知,當咱們經過setValue:forKey:
來設置值的時候,步驟以下框架
步驟一
:首先找這三種setter:
方法,分別是:set<Key>
->_set<Key>
->setIs<Key>
,其中<Key>
是成員變量的名字,且首字母大寫
,好比本文中的name
,順序就是setName
->_setName
->setIsName
。當找到這三種setter
中任意一個時,則進行賦值,若是沒有找到則進入步驟二
.步驟二
:判斷+ (BOOL)accessInstanceVariablesDirectly
函數是否返回YES,若是返回YES,則按照 _key
->_iskey
->key
->iskey
的順序搜索成員,找到任意一個則進行賦值,不然進入步驟三
;若是返回NO,則直接進入步驟三
。步驟三
:若是setter方法 或者 實例變量都沒有找到,系統會執行該對象的setValue:forUndefinedKey:
函數,默認拋出異常,因此咱們使用KVC
進行解析模型數據時,要實現setValue:forUndefinedKey:
函數,不然會崩潰。設值總結
當咱們調用valueForKey:
時,內部操做流程以下:ide
步驟一
:調用getter
方法,調用順序是:get<Key>
-> <key>
-> is<Key>
-> _<key>
,以name爲例,getName
-> name
-> isName
-> _name
,若是找到,則直接返回對應的值(多是對象),若是找不到則進入步驟二
步驟二
:判斷+ (BOOL)accessInstanceVariablesDirectly
函數是否返回YES,若是爲YES,則訪問成員變量,順序爲:_<key>
->_is<Key>
-><key>
-> is<Key>
,以name爲例則是_name
->_isName
->name
-> isName
,找到則返回對應的值(多是對象),找不到則進入步驟三
;若是返回的是NO,則截止進入步驟三
。步驟三
:均找不到,則調用valueForUndefinedKey:
拋出異常。取值總結
: