背景:
去年定的数据模型,当时为省事,以服务器返回的字段作为属性,整件模型类只定义几个属性,直接采用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"}