Objective

KVC的使用


1、KVC 全称 key valued coding 键值编码

反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性.JAVA,C#都有这个机制。ObjC也有,所以你根部不必进行任何操作就可以进行属性的动态读写,就是KVC。

KVC的操作方法由NSKeyValueCoding提供,而他是NSObject的类别,也就是说ObjC中几乎所有的对象都支持KVC操作。

2、常用方法

获取值的方法

valueForKey:,传入NSString属性的名字。

valueForKeyPath:,传入NSString属性的路径,xx.xx形式。

valueForUndefinedKey它的默认实现是抛出异常,可以重写这个函数做错误处理。

那么问题来了 现在有连个类,Book类(对应属性:name,prices)和Person类(对应属性:name,height,Book *book),person有一本名字叫做《太阳的后裔》,那么现在想通过KVC给这本书赋值,应该如何操作?

个人总结答案:因为现在想修改的不是对应类也就是Person类的属性,是要修改Book的属性(person.book),所以需要通过valueForKeyPath来进行修改^_^                     

                               


修改值的方法

setValue:forKey:

setValue:forKeyPath:

setValue:forUndefinedKey:

 setValue:forKey的搜索过程:

  1. 用@property定义的属性的key值(这里指的是property 系统生成的setter、getter方法 )
  2. setter方法的key值(用户自定义的setter方法)
  3. 直接访问成员变量,先找key,如果找不到,再找_key
  4. 以上三种都未找到就会调用- (void)setValue:(id)value forUndefinedKey:(NSString *)key 方法。
  5. 如果没有重写setValue:forUndefinedKey程序会马上崩溃。

注意:

1、使用KVC间接修改对象属性时,系统会自动判断对象属性的类型,并完成转换。

2、KVC可以访问成员变量,无论是否提供getter/setter方法,无论可见性是怎样,是否有readonly修饰。

 setValue:forUndefinedKey与valueForUndefinedKey的应用

KVC的主要用途无非是ORM映射,就是将dictionary转换成model,但有些服务器返回的字段有可能是oc的关键字比如‘id’,’description’等。如上代码举得id的例子,我们无法让@property后面key值为id,于是使用大写的ID代替,KVC是区分大小写的我们不用担心。这时我们只需在setValue:forUndefinedKey把id的key值赋值给ID的key值,就可以避免关键字的尴尬。 

3、dict <->model 互转

字典转模型

[self setValuesForKeysWithDictionary:dict];

模型转字典

[p dictionaryWithValuesForKeys:array];

4、KVC集合

NSArray/NSSet等都支持KVC

[array valueForKeyPath:@"dog.name"];

5、使用KVC计算属性

格式为:[p valueForKeyPath:@"Left keypath部分.@Collectionoperator部分.Right keypath部分”];

Left keypath部分:需要操作对象路径。

Collectionoperator部分:通过@符号确定使用的集合操作。

Right keypath部分:需要进行集合操作的属性。

举例:[p valueForKeyPath:@"books.@sum.price"];

@avg:平均值

@count:总数

@max:最大

@min:最小

@sum:总数

6、具体代码与实际编辑

1)当使用KVC给对象的属性赋值时,当根据输入的Key值没有找到对应的Value时调用

1 - (void)setValue:(id)value forUndefinedKey:(NSString *)key {
2     
3     NSLog(@"key = %@没有找到",key);
4     
5 }

2)当找到了对应的key值,代码为

 1 //
 2 //  main.m
 3 //  KVC熟悉与加强
 4 //
 5 //  Created by ma c on 16/5/16.
 6 //  Copyright © 2016年 彭盛凇. All rights reserved.
 7 //
 8 
 9 #import <Foundation/Foundation.h>
10 
11 #import "Model.h"
12 
13 int main(int argc, const char * argv[]) {
14     @autoreleasepool {
15         
16         Model *model =  [[Model alloc] init];
17         
18         [model setValue:@"Coder丶PSS" forKey:@"name"];
19         [model setValue:@"178" forKeyPath:@"height"];
20         
21 //        NSLog(@"%@",model);
22         
23         NSLog(@"名字叫%@,身高为%@",[model valueForKey:@"name"],[model valueForKey:@"height"]);
24         
25         
26         
27     }
28     return 0;
29 }

结果为:

3)使用原生方法解析数据

因为本人没有服务器,写了个假数据(plist),进行解析,效果是一样的

(1)plist:

(2)解析数据代码

 model.m

 1 //
 2 //  Model.h
 3 //  KVC熟悉与加强
 4 //
 5 //  Created by ma c on 16/5/16.
 6 //  Copyright © 2016年 彭盛凇. All rights reserved.
 7 //
 8 
 9 #import <Foundation/Foundation.h>
10 
11 @interface Model : NSObject
12 
13 @property (nonatomic, copy, readonly) NSString *name;
14 
15 @property (nonatomic, assign, readonly) NSInteger height;
16 
17 + (NSArray *)loadData;
18 
19 @end

model.h

 1 //
 2 //  Model.m
 3 //  KVC熟悉与加强
 4 //
 5 //  Created by ma c on 16/5/16.
 6 //  Copyright © 2016年 彭盛凇. All rights reserved.
 7 //
 8 
 9 #import "Model.h"
10 
11 @implementation Model
12 
13 - (NSString *)description
14 {
15     return [NSString stringWithFormat:@"model.name = %@, mdoel.height = %@", _name, @(_height)];
16 }
17 
18 - (void)setValue:(id)value forUndefinedKey:(NSString *)key {
19     
20     NSLog(@"key = %@没有找到",key);
21     
22 }
23 
24 + (NSArray *)loadData {
25     
26     //获取plist文件路径
27     NSString *path = @"/Users/mac/Desktop/KVC熟悉与加强/KVC熟悉与加强/CoderPSS.plist";
28     
29     //获取plist文件中的数组
30     NSArray *array = [NSArray arrayWithContentsOfFile:path];
31     
32     //初始化可变数组
33     NSMutableArray *dataList = [NSMutableArray array];
34     
35     //使用字典遍历plist中的数组
36     for (NSDictionary *dict in array) {
37         
38         //初始化model类
39         Model *model = [[Model alloc] init];
40         
41         //使用KVC(setValuesForKeysWithDictionary)方法解析数据
42         [model setValuesForKeysWithDictionary:dict];
43         
44         //将model类加到可变数组
45         [dataList addObject:model];
46     }
47     
48     //返回可变数组
49     return dataList;
50 }
51 
52 @end

运行结果

原文地址:https://www.cnblogs.com/PSSSCode/p/5499510.html