KVC
目錄結(jié)構(gòu)
- KVC定義
- KVC取值和設(shè)置
- KVC使用keyPath
- KVC處理字典
- KVC作用
參考:
iOS KVC和KVO詳解:https://juejin.im/post/6844903602545229831
KVC/KVO 總結(jié):https://juejin.im/post/6844903705729302541#heading-1
KVC的定義
KVC(Key-value coding)鍵值編碼,就是指iOS的開發(fā)中,可以允許開發(fā)者通過Key名直接【訪問對象的屬性】,或者給對象的【屬性賦值】。而不需要調(diào)用明確的存取方法。這樣就可以在運(yùn)行時(shí)動(dòng)態(tài)地訪問和修改對象的屬性。而不是在編譯時(shí)確定,這也是iOS開發(fā)中的黑魔法之一。很多高級(jí)的iOS開發(fā)技巧都是基于KVC實(shí)現(xiàn)的。
KVC主要的的四個(gè)方法:
//1. 直接通過Key來取值
- (nullable id)valueForKey:(NSString *)key;
//2. 通過KeyPath來取值
- (nullable id)valueForKeyPath:(NSString *)keyPath;
//3. 通過Key來設(shè)值
- (void)setValue:(nullable id)value forKey:(NSString *)key;
//4. 通過KeyPath來設(shè)值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
一些其他的方法:
+ (BOOL)accessInstanceVariablesDirectly;
//默認(rèn)返回YES,表示如果沒有找到Set<Key>方法的話,會(huì)按照_key,_iskey,key,iskey的順序搜索成員,設(shè)置成NO就不這樣搜索
- (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
//KVC提供屬性值正確性?驗(yàn)證的API,它可以用來檢查set的值是否正確、為不正確的值做一個(gè)替換值或者拒絕設(shè)置新值并返回錯(cuò)誤原因。
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;
//這是集合操作的API,里面還有一系列這樣的API,如果屬性是一個(gè)NSMutableArray,那么可以用這個(gè)方法來返回。
- (nullable id)valueForUndefinedKey:(NSString *)key;
//如果Key不存在,且沒有KVC無法搜索到任何和Key有關(guān)的字段或者屬性,則會(huì)調(diào)用這個(gè)方法,默認(rèn)是拋出異常。
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
//和上一個(gè)方法一樣,但這個(gè)方法是設(shè)值。
- (void)setNilValueForKey:(NSString *)key;
//如果你在SetValue方法時(shí)面給Value傳nil,則會(huì)調(diào)用這個(gè)方法
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
//輸入一組key,返回該組key對應(yīng)的Value,再轉(zhuǎn)成字典返回,用于將Model轉(zhuǎn)到字典。
KVC賦值流程

KVC賦值
setValue:forKey:的默認(rèn)實(shí)現(xiàn)是給定key和value作為參數(shù)輸入,嘗試把value設(shè)置給以key命名的屬性。過程如下:
- 按序搜索set<Key>:或_set<Key>,如果找到,則使用輸入?yún)?shù)調(diào)用并結(jié)束。
- 如果沒有找到簡單的訪問器方法,并且如果類方法accessInstanceVariablesDirectly返回YES(默認(rèn)為YES),則按序搜索以下實(shí)例變量: _<key>/_is<Key>/<key>/is<Key>,如果找到了則直接進(jìn)行賦值并結(jié)束。
- 以上方法皆失敗則調(diào)用setValue:forUndefinedKey:,這個(gè)方法默認(rèn)拋出異常,NSObject的子類可以自定義。
KVC取值流程

KVC取值流程
valueForKey:的默認(rèn)實(shí)現(xiàn)是,給定key參數(shù)作為輸入,通過下面的過程,在接收valueForKey:調(diào)用的類實(shí)例中操作。
- 按順序搜索訪問器方法get<Key> / <key> / is<Key> / _<key>。如果找到,調(diào)用該方法并且?guī)е椒ǖ恼{(diào)用結(jié)果調(diào)轉(zhuǎn)到第5步執(zhí)行;否則,繼續(xù)下一步。
- 如果沒有找到簡單的訪問方法,搜索其名稱匹配某些模式的方法的實(shí)例。其中匹配模式包含countOf<Key>,objectIn<Key>AtIndex:(對應(yīng)于NSArray定義的基本方法),和<key>AtIndexs:(對應(yīng)于NSArray的方法objectsAtIndexs:)
一旦找到第一個(gè)和其他兩個(gè)中的至少一個(gè),則創(chuàng)建一個(gè)響應(yīng)所以NSArray方法并返回該方法的集合代理對象。否則,執(zhí)行第3步。代理對象隨后將任何NSArray接收到的一些組合的消息。 - 如果沒有找到簡單的訪問器方法或數(shù)組訪問方法組,則尋找三個(gè)方法countOf<Key>/enumeratorOf<Key>/memberOf<Key>:,對應(yīng)NSSet類的基本方法。
- 如果三個(gè)方法全找到了,則創(chuàng)建一個(gè)集合代理對象來響應(yīng)所有的NSSet方法并返回。否則,執(zhí)行第4步。
如果上面的方法都沒有找到,并且接受者的類方法accessInstanceVariablesDirectly返回YES(默認(rèn)YES),則按序搜索以下實(shí)例變量:_<key> / _is<Key> / <key> / is<Key>。如果找到其中之一,直接獲取實(shí)例變量的值并跳轉(zhuǎn)到第5步;否則執(zhí)行第6步。 - 如果檢索到的屬性值是對象指針,則只返回結(jié)果;如果值是受NSNumber支持的標(biāo)量,則將其存儲(chǔ)在NSNumber實(shí)例中并返回;如果結(jié)果是NSNumber不支持的標(biāo)量,則轉(zhuǎn)換成NSValue對象并返回
- 如果以上所有的嘗試都失敗了,則調(diào)用valueForUndefinedKey:,這個(gè)方法默認(rèn)拋出異常,NSObject的子類可以重寫來自定義行為。