iOS语法之KVC的使用

KVC简介
全称是Key-value coding,翻译成键值编码。顾名思义,在某种程度上跟map的关系匪浅。它提供了一种使用字符串而不是访问器方法去访问一个对象实例变量的机制。
KVC的应用
以下通过几个例子来说明KVC中得常用方法:

【iOS语法之KVC的使用】新建一个Student(学生)类
1
2
3
4
5
6
7
8
9
10
11

#import

@class Course;
@interface Student : NSObject {
NSString *name;
Course *course;
NSInteger point;
NSArray *otherStudent;
}

@end

新建一个Course(课程)类
1
2
3
4
5
6
7

#import

@interface Course : NSObject {
NSString *courseName;
}

@end

案例分析:
下面的例子结合了大部分常用的方法,通过注释可以很好地理解,也可以copy下来自己运行看看。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

//
//ViewController.m
//testOC
//
//Created by Benjamin on 1/2/16.
//Copyright ? 2016 Benjamin. All rights reserved.
//

#import "ViewController.h"
#import "Student.h"
#import "Course.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

[self useKey];
[self useKeyPath];
[self performCollection];
[self performDictionary];
}


/**
*.m文件也没有实现。name属性没有加property,原来的访问方法就访问不了name属性了。
使用KVC就可以轻松实现
*/
- (void)useKey {
Student *student = [[Student alloc] init];
[student setValue:@"Benjamin" forKey:@"name"];
NSString *name = [student valueForKey:@"name"];
NSLog(@"学生姓名:%@", name); //打印 学生姓名:Benjamin

NSLog(@"------------------------------------");
}

/**
*使用Keypath(键路径)访问属性
*/
- (void)useKeyPath {
Student *student = [[Student alloc] init];
[student setValue:@"Benjamin" forKey:@"name"];

Course *course = [[Course alloc] init];
[course setValue:@"语文课" forKey:@"courseName"];
[student setValue:course forKey:@"course"];
NSString *courseName = [student valueForKeyPath:@"course.courseName"];
NSLog(@"课程名称:%@", courseName); //打印 课程名称:语文课

[student setValue:@"数学课" forKeyPath:@"course.courseName"];
courseName = [student valueForKeyPath:@"course.courseName"];
NSLog(@"新课程名称:%@", courseName); //打印 新课程名称:数学课

//NSInteger也可以使用NSString包装使用
[student setValue:@"88" forKey:@"point"];
NSString *point = [student valueForKey:@"point"];
NSLog(@"point: %@", point); //打印 point: 88

//推荐用这种方式使用基本数据类型
[student setValue:[NSNumber numberWithInteger:88] forKey:@"point"];
NSNumber *newPoint = [student valueForKey:@"point"];
NSLog(@"newPoint: %@", newPoint); //打印 newPoint: 88

NSLog(@"------------------------------------");
}

/**
*操作集合
可以使用集合操作计算学生的平均分、最高分、总分、总人数等数据
*/
- (void)performCollection {
Student *student = [[Student alloc]init];
[student setValue:@"张三" forKey:@"name"];

Student *s1 = [[Student alloc] init];
Student *s2 = [[Student alloc] init];
Student *s3 = [[Student alloc] init];
[s1 setValue:@"77" forKey:@"point"];
[s2 setValue:@"88" forKey:@"point"];
[s3 setValue:@"99" forKey:@"point"];
NSArray *studentArray = [NSArray arrayWithObjects:s1, s2, s3, nil];
[student setValue:studentArray forKey:@"otherStudent"];
NSLog(@"其他学生的成绩: %@", [student valueForKeyPath: @"otherStudent.point"]);
NSLog(@"共有%@个学生", [student valueForKeyPath: @"otherStudent.@count"]);
NSLog(@"学生的总分: %@", [student valueForKeyPath: @"otherStudent.@sum.point"]);
NSLog(@"学生的最高分: %@", [student valueForKeyPath: @"otherStudent.@max.point"]);
NSLog(@"学生的最低分: %@", [student valueForKeyPath: @"otherStudent.@min.point"]);
NSLog(@"平均成绩: %@", [student valueForKeyPath: @"otherStudent.@avg.point"]);

/**
输出结果
2016-01-04 12:05:46.528 testOC[29855:945179] 其他学生的成绩: (
77,
88,
99
)
2016-01-04 12:05:46.529 testOC[29855:945179] 共有3个学生
2016-01-04 12:05:46.529 testOC[29855:945179] 学生的总分: 264
2016-01-04 12:05:46.529 testOC[29855:945179] 学生的最高分: 99
2016-01-04 12:05:46.529 testOC[29855:945179] 学生的最低分: 77
2016-01-04 12:05:46.529 testOC[29855:945179] 平均成绩: 88
**/

NSLog(@"------------------------------------");
}

/**
*操作字典
*/
- (void)performDictionary {
NSDictionary *dic = @{@"name": @"jack",
@"point": [NSNumber numberWithInteger:12]};
Student *student = [[Student alloc] init];
[student setValuesForKeysWithDictionary:dic];
NSLog(@"姓名为: %@, 分数为: %@", [student valueForKey: @"name"], [student valueForKey: @"point"]);

/**
结果为
姓名为: jack, 分数为: 12
**/

NSLog(@"------------------------------------");
}

/**
实际使用举例
利用kvc的这个特性,我们可以访问系统里的一些私有变量。
例如:在UIPageControl里面有两个私有变量:
UIImage *_currentPageImage;
UIImage *_pageImage;
*设置pageControl当前显示和未显示到脚标的样式了
*/
- (void)changePageControlImage {
UIPageControl *pageControl = [[UIPageControl alloc] init];
[pageControl setValue:[UIImage imageNamed:@"XX"] forKey:@"_currentPageImage"];
[pageControl setValue:[UIImage imageNamed:@"YY"] forKey:@"_pageImage"];
UIImage *currentImage = [pageControl valueForKey:@"_currentPageImage"];
UIImage *pageImage = [pageControl valueForKey:@"_pageImage"];
NSLog(@"currentImage: %@, pageImage: %@", currentImage, pageImage);

NSLog(@"------------------------------------");
}
@end

    推荐阅读