背景:
去年定的數據模型,當時爲省事,以服務器返回的字段作爲屬性,整件模型類只定義幾個屬性,直接採用setValuesForKeysWithDictionary,一直運行的挺好,今天服務器忽然想加一個字段,大面積的閃退報告來了。
雷區:
1、- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues ,使用時忽必要保證keyedValues中的鍵值都對屬性與之對應;
2、如果服務器端不確定,隨時可能擴展字段,你又想省事使用KVC,腫麼辦? 辦法就是重寫-(void)setValue:(id)value forUndefinedKey:(NSString *)key 和 -(void)setNilValueForKey:(NSString *)key,前者中處理返回字段超出定義的屬性,後者中處理返回字段爲空值的情況。
當然,有第三方庫解決此類bug,如MJExtension。
下面開扒NSObject(NSKeyValueCoding):
1、+ (BOOL)accessInstanceVariablesDirectly;
/**************************常規單個賦值或取值************************************/
2、- (nullable id)valueForKey:(NSString *)key;
返回指定鍵的值
3、- (void)setValue:(nullable id)value forKey:(NSString *)key;
指定鍵的值
4、- (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
5、- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;
6、- (NSMutableOrderedSet *)mutableOrderedSetValueForKey:(NSString *)key
7、- (NSMutableSet *)mutableSetValueForKey:(NSString *)key;
8、- (nullable id)valueForKeyPath:(NSString *)keyPath;
9、- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
10、- (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKeyPath:(NSString *)inKeyPath error:(out NSError **)outError;
11、- (NSMutableArray *)mutableArrayValueForKeyPath:(NSString *)keyPath;
12、- (NSMutableOrderedSet *)mutableOrderedSetValueForKeyPath:(NSString *)keyPath NS_AVAILABLE(10_7, 5_0);
13、- (NSMutableSet *)mutableSetValueForKeyPath:(NSString *)keyPath;
/**************************處理異常************************************/
14、- (nullable id)valueForUndefinedKey:(NSString *)key;
返回不存在鍵的值,重寫此方法 消除異常
15、- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
處理給不存在的鍵賦值,不重寫此方法出現未定義的鍵時程序會崩潰
16、- (void)setNilValueForKey:(NSString *)key;
處理返回鍵的值爲空,不重寫此方法出現鍵爲空時程序會崩潰
/**************************集體賦值或取值************************************/
17、- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
返回指定鍵組的鍵值對,如[name,age]返回@{@"name":@"qq",@"age":@"1"}
18、- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;
根據給定的字典給鍵賦值 如keyedValues=@{@"name":@"qq",@"age":@"1"}