KVC的查詢順序

一、自定義一個TestObject類,測試KVC取值的查詢順序

以下是TestObject的源碼,你沒看錯垃你,就是這樣一個沒有實(shí)現(xiàn)任何方法,沒有任何屬性的類喂很。我們用TestObject類來探究KVC取值的查詢順序惜颇。

.h
#import <Foundation/Foundation.h>

@interface TestObject : NSObject

@end

.m
#import "TestObject.h"

@interface TestObject()

@end

@implementation TestObject

@end


KVC不論取值還是賦值都會先去查詢相應(yīng)的方法,如果一個方法都沒找到少辣,再按規(guī)則去找成員變量凌摄。

我們在代碼中調(diào)用KVC的取值:
TestObject *obj = [TestObject new];
    
NSString *name = [obj valueForKey:@"name"];
    
NSLog(@"%@",name);
在未聲明屬性,未實(shí)現(xiàn)任何方法漓帅,類中無對應(yīng)成員變量時使用valueForKey:會直接崩潰锨亏。??(大家都知道)
直接崩潰.png

1.KVC取值查找的第一個方法getName

#import "TestObject.h"

@interface TestObject()

@end

@implementation TestObject

- (NSString *)getName {
    
    return @"getName";
}

@end

當(dāng)我們在TestObject類中實(shí)現(xiàn)了getName方法后,valueForKey:就不會再崩潰忙干,而是調(diào)用getName方法器予,獲取返回值。


控制臺打泳杵取:

image.png

2.TestObject類中如果沒有實(shí)現(xiàn)getName方法乾翔,KVC會查找第二個方法name,如果有getName方法施戴,就不會繼續(xù)往下查找了反浓,因?yàn)?code>getName方法已經(jīng)生效了萌丈。

#import "TestObject.h"

@interface TestObject()

@end

@implementation TestObject

//- (NSString *)getName {
//
//    return @"getName";
//}

- (NSString *)name {
    
    return @"name";
}



控制臺打印:

image.png

3.TestObject類中如果沒有實(shí)現(xiàn)getName方法雷则,也沒有實(shí)現(xiàn)name方法辆雾,KVC會查找第三個方法isName

#import "TestObject.h"

@interface TestObject()

@end

@implementation TestObject

//- (NSString *)getName {
//
//    return @"getName";
//}
//
//- (NSString *)name {
//
//    return @"name";
//}

- (NSString *)isName {
    
    return @"isName";
}



控制臺打忧缮簟:

image.png

4.若前三個方法都沒有實(shí)現(xiàn)乾颁,KVC會查找第四個方法_name

#import "TestObject.h"

@interface TestObject()

@end

@implementation TestObject

//- (NSString *)getName {
//
//    return @"getName";
//}
//
//- (NSString *)name {
//
//    return @"name";
//}

//- (NSString *)isName {
//
//    return @"isName";
//}

- (NSString *)_name {
    
    return @"_name";
}



控制臺打右照弧:

image.png

5.如果上述方法都沒實(shí)現(xiàn)英岭,接下來KVC會將要取的值看做數(shù)組,調(diào)用下面的方法:

- (NSUInteger)countOfName(必須實(shí)現(xiàn))
以下兩個二選一
- (id)objectInNameAtIndex:(NSUInteger)index(優(yōu)先查找)
- (id)nameAtIndexes:(id)indexes(其次查找)

6.以上方法都沒有找到湿右,那么KVC會按照集合(NSSet)來處理诅妹,調(diào)用下面三個方法:

- (NSUInteger)countOfName(必須實(shí)現(xiàn))
- (id)enumeratorOfName(必須實(shí)現(xiàn))
- (id)memberOfName:(id)name(必須實(shí)現(xiàn))

7.方法查詢到此為止,如果上述方法都沒有查找到毅人,接下來會按照順序查找成員變量:

_name;
_isName;
name;
isName;

  • 第一次調(diào)用:
源碼:
#import "TestObject.h"

@interface TestObject(){
    NSString *_name;
    NSString *_isName;
    NSString *name;
    NSString *isName;
}

@end

@implementation TestObject

- (instancetype)init
{
    self = [super init];
    if (self) {
        _name = @"ivar : _name";
        _isName = @"ivar : _isName";
        name = @"ivar : name";
        isName = @"ivar : isName";
    }
    return self;
}
控制臺:
image.png
  • 當(dāng)類中沒有_name成員變量時吭狡,我們進(jìn)行第二次調(diào)用:
源碼:
#import "TestObject.h"

@interface TestObject(){
//    NSString *_name;
    NSString *_isName;
    NSString *name;
    NSString *isName;
}

@end

@implementation TestObject

- (instancetype)init
{
    self = [super init];
    if (self) {
//        _name = @"ivar : _name";
        _isName = @"ivar : _isName";
        name = @"ivar : name";
        isName = @"ivar : isName";
    }
    return self;
}
控制臺:
image.png
  • 當(dāng)類中沒有_isName成員變量時,我們進(jìn)行第三次調(diào)用:
源碼:
#import "TestObject.h"

@interface TestObject(){
//    NSString *_name;
//    NSString *_isName;
    NSString *name;
    NSString *isName;
}

@end

@implementation TestObject

- (instancetype)init
{
    self = [super init];
    if (self) {
//        _name = @"ivar : _name";
//        _isName = @"ivar : _isName";
        name = @"ivar : name";
        isName = @"ivar : isName";
    }
    return self;
}
控制臺:
image.png
  • 當(dāng)類中沒有name成員變量時丈莺,我們進(jìn)行第四次調(diào)用:
源碼:
#import "TestObject.h"

@interface TestObject(){
//    NSString *_name;
//    NSString *_isName;
//    NSString *name;
    NSString *isName;
}

@end

@implementation TestObject

- (instancetype)init
{
    self = [super init];
    if (self) {
//        _name = @"ivar : _name";
//        _isName = @"ivar : _isName";
//        name = @"ivar : name";
        isName = @"ivar : isName";
    }
    return self;
}

控制臺:
image.png

8.如果上述方法和成員變量都沒找到划煮,KVC會走最后一步(id)valueForUndefinedKey:(NSString *)key,若次方法依然沒有找到缔俄,程序崩潰弛秋。


二、定義一個TestObject2類俐载,測試KVC賦值的查詢順序

以下是TestObject2的源碼:
.h
#import <Foundation/Foundation.h>

@interface TestObject2 : NSObject

@end

.m
#import "TestObject2.h"

@interface TestObject2()

@end

@implementation TestObject2

@end

我們在代碼中調(diào)用KVC的賦值:
TestObject2 *obj = [TestObject2 new];
    
[obj setValue:@"TestString" forKey:@"name"];

在未聲明屬性蟹略,未實(shí)現(xiàn)任何方法,類中無對應(yīng)成員變量時使用setValue: forKey:會直接崩潰遏佣。??(這個大家也知道)

1.KVC賦值查找的第一個方法setName:

#import "TestObject2.h"

@interface TestObject2()

@end

@implementation TestObject2

- (void)setName:(NSString *)name {
    NSLog(@"%s\t%@",__func__,name);
}

@end



控制臺打油诰妗:

image.png

2.如果setName:沒有找到,KVC會查找第二個方法_setName:

#import "TestObject2.h"

@interface TestObject2()

@end

@implementation TestObject2

//- (void)setName:(NSString *)name {
//    NSLog(@"%s\t%@",__func__,name);
//}

- (void)_setName:(NSString *)name {
    NSLog(@"%s\t%@",__func__,name);
}

@end



控制臺打印:

image.png

3.如果前面兩個方法都沒有找到状婶,接下來會調(diào)用(BOOL)accessInstanceVariablesDirectly意敛,如果返回NO則不去查找成員變量,如果返回YES則接下來按照下列順序規(guī)則查找成員變量膛虫。

_name;
_isName;
name;
isName;

  • 第一次調(diào)用:
源碼:
#import "TestObject2.h"

@interface TestObject2(){
    NSString *_name;
    NSString *_isName;
    NSString *name;
    NSString *isName;
}
@end

@implementation TestObject2

+ (BOOL)accessInstanceVariablesDirectly {
    return YES;
}

- (void)printName {
    NSLog(@"_name : %@",_name);
    NSLog(@"_isName : %@",_isName);
    NSLog(@"name : %@",name);
    NSLog(@"isName : %@",isName);
}

@end
控制臺:
image.png
  • 當(dāng)類中沒有_name成員變量時空闲,我們進(jìn)行第二次調(diào)用:
源碼:
#import "TestObject2.h"

@interface TestObject2(){
//    NSString *_name;
    NSString *_isName;
    NSString *name;
    NSString *isName;
}
@end

@implementation TestObject2

+ (BOOL)accessInstanceVariablesDirectly {
    return YES;
}

- (void)printName {
//    NSLog(@"_name : %@",_name);
    NSLog(@"_isName : %@",_isName);
    NSLog(@"name : %@",name);
    NSLog(@"isName : %@",isName);
}

@end
控制臺:
image.png

后面兩個成員變量我就不貼出來了,以此類推走敌。

4.如果上述方法和成員變量都沒找到碴倾,并且(BOOL)accessInstanceVariablesDirectly返回NO,KVC會走最后一步setValue:(id)value forUndefinedKey:(NSString *)key,若次方法依然沒有找到,程序崩潰跌榔。


以上均為手打异雁,如果錯誤敬請指正交流。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末僧须,一起剝皮案震驚了整個濱河市纲刀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌担平,老刑警劉巖示绊,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異暂论,居然都是意外死亡面褐,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門取胎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來展哭,“玉大人,你說我怎么就攤上這事闻蛀》税” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵觉痛,是天一觀的道長役衡。 經(jīng)常有香客問我,道長薪棒,這世上最難降的妖魔是什么映挂? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮盗尸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘帽撑。我一直安慰自己泼各,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布亏拉。 她就那樣靜靜地躺著扣蜻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪及塘。 梳的紋絲不亂的頭發(fā)上莽使,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機(jī)與錄音笙僚,去河邊找鬼芳肌。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亿笤。 我是一名探鬼主播翎迁,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼净薛!你這毒婦竟也來了汪榔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤肃拜,失蹤者是張志新(化名)和其女友劉穎痴腌,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體燃领,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡士聪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了柿菩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片戚嗅。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖枢舶,靈堂內(nèi)的尸體忽然破棺而出懦胞,到底是詐尸還是另有隱情,我是刑警寧澤凉泄,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布躏尉,位于F島的核電站,受9級特大地震影響后众,放射性物質(zhì)發(fā)生泄漏胀糜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一蒂誉、第九天 我趴在偏房一處隱蔽的房頂上張望教藻。 院中可真熱鬧,春花似錦右锨、人聲如沸括堤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽悄窃。三九已至,卻和暖如春蹂窖,著一層夾襖步出監(jiān)牢的瞬間轧抗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工瞬测, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留横媚,地道東北人纠炮。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像分唾,于是被迫代替她去往敵國和親抗碰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容