在開發(fā)中,我們可以通過使用 KVC 的方式來對某個對象的屬性進(jìn)行賦值/取值操作。
經(jīng)常會用到以下 API:
// 設(shè)置值
- (void)setValue:(nullable id)value forKey:(NSString *)key;
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
// 獲取值
- (nullable id)valueForKeyPath:(NSString *)keyPath;
- (nullable id)valueForKey:(NSString *)key;
1、賦值操作
KVC的調(diào)用原理:
如果我們給某個類定義一個屬性,那么編譯器會自動生成getter和setter方法,如果通過KVC給該屬性進(jìn)行賦值操作,默認(rèn)會調(diào)用setter方法進(jìn)行賦值,但是這不能完全搞清楚KVC是如何工作的。
現(xiàn)在我們定義一個Person類,但是我們并不給Person定義任何的屬性,接下來創(chuàng)建person對象,通過KVC的方式給person的age屬性進(jìn)行賦值操作。
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *person = [[Person alloc] init];
[person setValue:@(40) forKey:@"age"];
}
return 0;
}
接下來是執(zhí)行順序,去Person類中查找有沒有- (void)setAge:方法,如果有那么就進(jìn)行賦值操作;如果沒有再去查找有沒有- (void)_setAge: 方法,如果有就進(jìn)行賦值的操作,如果以上2個方法都沒找到,那么就會調(diào)用- (Bool)accessInstanceVariablesDirectly 方法,該方法是詢問是否可以直接訪問成員變量,返回NO就直接拋出異常未定的key,返回YES(如果不實(shí)現(xiàn)該方法默認(rèn)返回就是YES),那么就直接去成員變量中按順序查找以下成員變量:_age、_isAge、age、isAge。如果找到4個成員變量中的1位,那么就進(jìn)行賦值,否則拋出異常未定義的key。
2、取值操作
KVC 的取值操作也會按照一定的順序進(jìn)行操作的。
在取值的過程中,按照-(int)getAge、-(int)age、-(int)isAge、-(int)_age順序進(jìn)行,看有沒有實(shí)現(xiàn)這4個方法中的其中1個,如果有那么調(diào)用,如果沒有實(shí)現(xiàn)上面的4個方法,繼續(xù)查看 + (BOOL)accessInstanceVariablesDirectly 方法的返回值是否為 YES,如果為NO,直接拋出異常,如果為YES,那么就去按順序查找Person的成員變量是不是_age,_isAge、age、isAge中的一個,如果有4個成員變量中的1個,那么就取他們的值。