在KVC的實現(xiàn)中秽澳,依賴setter和getter的方法實現(xiàn),所以方法命名應該符合蘋果要求的規(guī)范,否則會導致KVC失敗滥崩。
setValue的過程
先看一個很有趣的問題
@interface ViewController ()
@property (nonatomic, strong) NSString *Str;
@property (nonatomic, strong) NSString *str;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 情況1
self.Str = @"大寫";
self.str = @"小寫";
NSLog(@"str:%@----Str:%@",_str,_Str);
// 輸出 str:(null)----Str:小寫
// 情況2
// self.Str = @"大寫";
self.str = @"小寫";
NSLog(@"str:%@----Str:%@",_str,_Str);
// 輸出 str:(null)----Str:小寫
// 情況3
self.Str = @"大寫";
// self.str = @"小寫";
NSLog(@"str:%@----Str:%@",_str,_Str);
// 輸出 str:(null)----Str:大寫
}
輸出:(null)----123
也就是說据忘,當有同名大小寫屬性時鹦牛,遵守駝峰標識的屬性會失效,也就是小寫開頭的屬性
為什么小寫開頭的屬性會失效呢勇吊?曼追??
我們從setter
方法找起
我們會發(fā)現(xiàn)oc
的setter
方法是遵守駝峰標識的汉规,比如setStr:(NSString *)Str
所以我的猜想:既然是setStr
礼殊。。针史。晶伦。。那么有_Str
的實例變量就優(yōu)先給他賦值啄枕,沒有就給_str
賦值
我們嘗試下
[self setValue:@"大寫" forKey:@"Str"];
[self setValue:@"小寫" forKey:@"str"];
結果還是一樣
回歸主題婚陪,我們調(diào)用[self setValue:@"大寫" forKey:@"Str"];
這個的時候,會先調(diào)用這個屬性的set方法.
那么問題也來了频祝,如果這時候的key是沒有的屬性或者nil泌参,那么就會導致調(diào)用setKey的時候脆淹,找不到方法導致崩潰
所以,我們可以封裝類似醬紫的安全方法
- (void)safeSetValue:(NSString *)value forKey:(NSString *)key
{
if (![key isKindOfClass:[NSString class]])
{
return;
}
@try {
[self setValue:value forKey:key];
}@catch(NSException *exception){}@finally {}
}
沒有找到setKey:
方法的時候
KVC機制會檢查
+ (BOOL)accessInstanceVariablesDirectly
方法有沒有返回YES沽一,默認該方法會返回YES盖溺,如果你重寫了該方法讓其返回NO的話,那么在這一步KVC會執(zhí)行setValue:forUNdefinedKey:
方法
一般我們不會閑得蛋疼去重寫+ (BOOL)accessInstanceVariablesDirectly
方法锯玛,
所以這時候既然setKey:
方法找不到了咐柜,就只能硬干了,直接去找對應的成員變量賦值攘残,
所以說拙友,就算是只讀屬性(只讀屬性沒有set方法),這時候用kvc也可以賦值歼郭,因為找不到set
方法遗契,直接對成員變量賦值
那如果找不到成員變量呢?病曾?牍蜂?
如果都沒有找到,那么就只能調(diào)用valueforUndefinedKey
和setValue:forUNdefinedKey:
(沒有定義這個key)拋異常
應用
提一個問題:+ (BOOL)accessInstanceVariablesDirectly
什么時候重寫這個方法泰涂,返回NO
但我們重寫這個方法鲫竞,返回NO的時候,外部對這個類進行kvc的時候逼蒙,就沒那么容易了从绘,因為當找不到set方法,就直接失敗了嘛
所以你想要這個類是牢,足夠封閉僵井,安全的時候,可以重寫這個方法驳棱,尤其是設置SDK的時候使用
字典轉模型
服務端返回字段批什,有可能是id,或者其他oc的系統(tǒng)保留字段
那么就可以重寫這方法社搅,在這塊地方去統(tǒng)一處理
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
}
valueForKey:搜索過程
有點多驻债,復雜
Tips
如果valueForKeyPath:方法的調(diào)用者是數(shù)組,那么就是去訪問數(shù)組元素的屬性值
應用:模型轉字典