鍵值編碼-KVC

KVC全稱是Key Value Coding,允許開發(fā)者通過key直接訪問對象的屬性,對對象的屬性進(jìn)行賦值??梢栽谶\行時動態(tài)的訪問和修改對象的屬性。


  • KVC最常用的兩個方法也是最基本的操作方法:
  1. setValue: forKey:為指定的屬性設(shè)置值
  2. valueForKey:獲取指定屬性的值。

  • KVC的簡單用法
    定義一個Person類
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;
@end

@implementation Person

- (void)setName:(NSString *)name {
    _name = name;
    NSLog(@"setName被調(diào)用");
}

@end

然后通過KVC的方式給Person類的屬性賦值:

Person *person = [[Person alloc] init];
[person setValue:@"張三" forKey:@"name"];
[person setValue:[NSNumber numberWithInt:11] forKey:@"age"];
NSLog(@"person.name=%@",[person valueForKey:@"name"]);
NSLog(@"person.age=%@",[person valueForKey:@"age"]);

控制臺輸出如下:

屏幕快照 2019-01-02 21.28.40.png

可以看到對Person類的屬性賦值成功了。并且- (void)setName:(NSString *)name方面被調(diào)用了。
將代碼修改為下面這樣:

@interface Person : NSObject {
    NSString *_name;
    NSString *name;
}
//@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;
@end

name賦值:

Person *obj = [[Person alloc] init];
[obj setValue:@"小明" forKey:@"name"];

通過查看obj實例可以看出是_name被賦值了。

屏幕快照 2019-01-02 21.43.54.png

將代碼更改為

@interface Person : NSObject {
    NSString *_isName;
    NSString *name;
}
//@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;
@end

調(diào)用代碼不變,可以看到_isName被賦值了

屏幕快照 2019-01-02 21.45.53.png

將代碼修改為

@interface Person : NSObject {
    NSString *isName;
    NSString *name;
}
//@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;
@end

再次運行,結(jié)果為name被賦值。

屏幕快照 2019-01-02 21.49.40.png


setValue: forKey:的底層實現(xiàn)機(jī)制:

[person setValue:@"張三" forKey:@"name"]來舉例說明。

  1. 先尋找Person類的setName方法,使用setter方法完成賦值。
  2. 如果沒有找到setName:方法,KVC機(jī)制會檢查+ (BOOL)accessInstanceVariablesDirectly方法有沒有返回YES,默認(rèn)該方法會返回YES,如果你重寫了該方法讓其返回NO的話,那么在這一步KVC會執(zhí)行setValue:forUndefinedKey:方法
  3. 如果Person類中沒有setName方法,KVC會依次去搜索_name,_isName,name,isName成員變量去進(jìn)行賦值操作。無論這些成員變量在什么地方定義和什么控制符修飾,都會進(jìn)行賦值操作。
  4. 如果上述三條都沒找到,會調(diào)用setValue:forUndefinedKey:的方法,拋出異常。

在上面的例子中再增加一條代碼,對Person類中沒有的屬性進(jìn)行賦值。

[person setValue:@"dog" forKey:@"dog"];

運行代碼,看到控制臺報錯

屏幕快照 2017-12-25 下午10.06.47.png

可以看到調(diào)用了setValue:forUndefinedKey:方法,程序結(jié)束。如果這不是我們想要的結(jié)果,我們可以重寫這個方法。

- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
    NSLog(@"你嘗試設(shè)置的key=%@不存在",key);
}

這樣就可以避免程序因異常而結(jié)束。


valueForKey:的底層實現(xiàn)機(jī)制:
[person valueForKey:@"name"]來舉例說明。

  1. 先尋找Person類的name方法,使用getter方法完成取值。
  2. KVC機(jī)制會檢查+ (BOOL)accessInstanceVariablesDirectly方法有沒有返回YES,默認(rèn)該方法會返回YES,如果你重寫了該方法讓其返回NO的話,那么在這一步KVC會執(zhí)行valueForUndefinedKey:方法
  3. 如果Person類中沒有name方法,KVC會依次去搜索_name,_isName,name,isName成員變量去進(jìn)行取值。無論這些成員變量在什么地方定義和什么控制符修飾,都會進(jìn)行取值。
  4. 如果上述三條都沒找到,會調(diào)用valueForUndefinedKey:的方法,拋出異常。

在上面的例子中再增加一條代碼,對Person類中沒有的屬性進(jìn)行賦值。

NSLog(@"person.dog=%@",[person valueForKey:@"dog"]);

控制臺打?。?/p>

屏幕快照 2017-12-25 下午10.20.00.png

可以看到調(diào)用了valueForUndefinedKey:的方法,程序因異常結(jié)束。同樣可以重寫valueForUndefinedKey:來避免程序異常結(jié)束。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • KVC KVC -- Key Value Coding 鍵值編碼 鍵值編碼的基本概念鍵值編碼是一個用于簡介訪問對象...
    生如夏花逝如秋葉閱讀 1,398評論 0 2
  • KVC簡介 我們知道可以通過setter、getter方法來設(shè)置和修改對象的屬性,也知道如何通過簡化的點語法來設(shè)置...
    請叫我周小帥閱讀 548評論 0 1
  • KVC(Key-value coding)鍵值編碼,單看這個名字可能不太好理解。其實翻譯一下就很簡單了,就是指iO...
    朽木自雕也閱讀 1,709評論 6 1
  • lua 的值類型 lua 是動態(tài)類型的語言,即是說類型附著于值而不是變量。在 lua 腳本里,變量是沒有類型的,只...
    董噠噠閱讀 2,833評論 1 1
  • 從日記小白到日記達(dá)人,我是日記星球174號星寶靜待花開,正在參加日記星球第4期21天蛻變之旅。我承諾每天堅持寫一篇...
    心理師劉津伶閱讀 516評論 0 3

友情鏈接更多精彩內(nèi)容