探索底層原理,積累從點滴做起。大家好,我是Mars。
往期回顧
iOS底層原理探索—OC對象的本質
iOS底層原理探索—class的本質
iOS底層原理探索—KVO的本質
今天帶領大家探索iOS之KVC的本質。
KVC
KVC全稱是Key-Value Coding,鍵值編碼,可以通過Key
來訪問和修改屬性。
KVC常用的API包括:
//存值
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (void)setValue:(id)value forKey:(NSString *)key;
//取值
- (id)valueForKeyPath:(NSString *)keyPath;
- (id)valueForKey:(NSString *)key;
KVC的使用
下面我們簡單使用一下KVC:
通過代碼可以看到,通過KVC我們給Person對象的
age
屬性進行了賦值和取值的操作,同時還使用setValue: forKeyPath:
方法做了一下相對復雜的Person對象中student的height
屬性做了賦值和取值。其中Person和Student的關系如下:setValue:forKey:
只是根據屬性名做賦值和取值的操作,而setValue: forKeyPath:
方法則能根據key
的路徑做一些層級間的復雜訪問操作。
KVC底層原理
KVC賦值
KVC賦值的底層原理就是,當我們調用setValue: forKeyPath:
方法后,系統會按照順序查找兩個方法:setKey
和_setKey
,如果實現了這兩個方法其中一個,那么就會傳遞參數,并且調用實現的方法。我們驗證一下:
我們通過代碼來設置Person的age
屬性,并且在Person類里面依次分別實現setAge
和_setAge
兩個方法
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *person = [[Person alloc] init];
// 通過KVC修改age屬性
[person setValue:@10 forKey:@"age"];
}
return 0;
}
Person類.m文件中的實現:
#import "Person.h"
@implementation Person
- (void)setAge:(int)age
{
NSLog(@"setAge: - %d", age);
}
//- (void)_setAge:(int)age
//{
// NSLog(@"_setAge: - %d", age);
//}
@end
第一次測試我們先注釋掉_setAge
方法,打印輸出
setAge:- 10
第二次測試我們注釋掉setAge
方法,去掉_setAge
的注釋:
#import "Person.h"
@implementation Person
//- (void)setAge:(int)age
//{
// NSLog(@"setAge: - %d", age);
//}
- (void)_setAge:(int)age
{
NSLog(@"_setAge: - %d", age);
}
@end
打印輸出
_setAge: - 10
第三次測試我們將注釋全部去掉:
#import "Person.h"
@implementation Person
- (void)setAge:(int)age
{
NSLog(@"setAge: - %d", age);
}
- (void)_setAge:(int)age
{
NSLog(@"_setAge: - %d", age);
}
@end
打印輸出
setAge:- 10
通過測試我們可以驗證我們上面的結論。
如果沒有實現setKey
和_setKey
這兩個方法的話,會繼續調用accessInstanceVariablesDirectly
方法,這個方法的返回值是BOOL類型,;如果返回值是NO,那么會調用setValue:forUndefinedKey:
方法,并拋出異常NSUnknownKeyException
的異常,賦值失敗。如果返回值是YES,那么會繼續按照順序依次查找按照_key
、_isKey
、key
、isKey
這四個成員變量,如果找到其中某個成員變量,完成賦值。如果四個成員變量全部未找到,那么會調用setValue:forUndefinedKey:
方法,并拋出異常NSUnknownKeyException
的異常,賦值失敗。
值得注意的是,accessInstanceVariablesDirectly
方法返回值默認是YES。
我們用流程圖總結如下:
KVC取值
KVC取值流程和賦值流程一樣,我們直接用流程圖總結一下:
關于KVC的底層原理探索我們告一段落,如有疑問,歡迎在評論區留言。
iOS進階
iOS進階.jpg