需求一:将字典转换成自己需的对象,对象的属性是字典的key值,直接使用key值获取数据存在两个缺点,一是key值难以记忆,二是直接使用key值Xcode不会有智能提示,很容易导致未知的错误。使用模型时,可以直接通过点语法将需要的数据点出,保证数据准确无误。使用模型的优点还在于存储、传值都比较方便,不容易出错。最主要的是这也符合我们MVC和MVVM的设计模式。
注意:要使用模型就离不开KVC,假如我们从外界传入一个字典,字典中有两个 key对应的值是我们需要的,这两个值分别是 “name”、“age”。要使用KVC的时候要注意模型的属性一定要和字典中的key值相对应。比如字典中的“name”,那模型中就必须有一个name的属性。这样就可以使用KVC了,KVC的两种方法:(下文都默认我们有两个模型属性,分别是name和age,传入的字典默认为dict)
1. setValue(模型属性, forKey:字典的key值)
eg:setValue(self.name, forKey:dict[“name”])
*这种赋值方法很麻烦,每需要一个key值就要打一遍该方法。这样的赋值方式就和self.name = dict[“name”] 的区别不是太大
2. setValuesForKeysWithDictionary(传入的字典)
eg: setValuesForKeysWithDictionary(dict)
*直接完成赋值,其实setValuesForKeysWithDictionary(传入的字典),它默认也是调用setValue(模型属性, forKey:字典的key值 ),遍历字典一一给模型属性赋值。所以使用KVC时就要求模型的属性必须喝字典的key值一一对应。
需求二:如果我们只想使用字典中的部分值呢?一个大字典,里面有好几十个key,难道我们还要在模型中根据key值定义几十个属性么?当然我们程序猿都是很懒的,肯定不会定义这么多key值的,此时我们只需重写KVC的以下方法就行了:
3.setValue(value: AnyObject?, forUndefinedKey key: String)
*这个方法会帮我们过滤我们没有的key值,值执行 setValuesForKeysWithDictionary(dict)时,当监测出我们没有字典中key值所对应的属性时就会调用这个方法。
*重写时里面不需要写任何代码,如果想打印哪些key值我们没有时就可以在里面打印。
需求三:我们知道很多字典中都有“id”这个key值。而“id”在我们iOS中是个数据类型,显然不能将“id”当作模型属性名称去定义。此时我们只需要随意定义一个属性名去保存“id”,当然为了更已读、严谨一些,我们一般还是定义为“ID”最为恰当。而我们知道要使用KVC就要key值和模型名一一对应,但是我们就是想要获取“id”。此时需要将“需求一”和“需求二”结合起来看了。我们在获取“id”时,直接使用传入的字典赋值:(此时我们新添一个属性“ID”)
eg :self.ID = dict[“id”]
*当这样赋值之后就取出”id “所对应的value了。
但是我们还要获取其他的value呢,此时在使用 setValuesForKeysWithDictionary(dict)完成其他属性的赋值。当然也需要重写setValue(value: AnyObject?, forUndefinedKey key: String)方法,因为字典中并有“ID”这个key值(字典中是“id”,“ID”是模型新定义的属性)。完整代码如下 :
swift:
override init() {
super.init()
self.ID = dict[@"id”];
setValuesForKeysWithDictionary(dict)
}
override func setValue(value: AnyObject?, forUndefinedKey key: String) { }
OC:
+ (instancetype) testWithDict:(NSDictionary *)dict{
TEST *test = [[TEST alloc]init];
test.ID = dict[@"id"];
[test setValuesForKeysWithDictionary:dict];
return test;
}
?
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
}
?
*注意当在对象方法使用KVC时一定要先super.init,因为要首先保证有一个对象存在,这样才能访问这个对象的属性。
*注意在使用对象方法时,命名方法名时“With”中的“W”必须大写,否则无法完成super.init
eg:- (instancetype) initWithDict:(NSDictionary *)dict
补充:KVC强大不仅仅只在于给模型赋值,KVC还可给只读 属性赋值,改变私有属性。比如UITabBarController中tabBar是只读属性,用一般的赋值时无法给只读属性赋值的,但是通过
setValue(value,forKey:”属性名”)
eg:setValue(value,forKey:“tabBar”)
?
总结:KVC是Set Value Coding的简称,它是一种直接通过字符串的名字(key)来访问类属性的机制。而不是通过Setter(设置器)和Getter(读取器)。