代码改变世界

梳理一下KVC

2016-03-10 18:43  蓝梦儿  阅读(401)  评论(0编辑  收藏  举报

  对于KVC,面试中会遇到,以前以为自己很了解,但当人家问到就老蒙圈,现在总结一下,以下内容来自或官方文档,或技术博客,或个人发挥。。。

一、访问成员变量

1)定义一个Student类,继承于NSObject。

.h

@interface Student : NSObject
{
    NSString *name;
}

@property (nonatomic, assign) int age;
@end

.m

#import "Student.h"

@implementation Student

@end

2)想要访问name,咋办呢?用KVC。 main中代码如下:

#import "Student.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {        
        Student *student = [[Student alloc]init];
        [student setValue:@"Doris" forKey:@"name"];
        NSString *name = [student valueForKey:@"name"];
        NSLog(@"name:%@",name);
        }
    return 0;
}

打印结果:

2016-03-10 17:23:51.518 KVC[9547:394677] name:Doris

 

3)现在name通过KVC赋值成功,也能用valueForKey取出值。那我们赋值的这个name是在Student中定义的成员变量name吗?添加一段代码试一下:

 [student setValue:@"" forKey:@"sex"];
 NSString *sex = [student valueForKey:@"sex"];
 NSLog(@"student sex:%@",sex);

编译没错,运行发现程序崩溃了!,错误如下:

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<Student 0x100604b60> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key sex.'

提示没有这个sex 这个key,所以KVC赋值的一定是存在的成员变量或属性。下面看一下age这个属性,直接用点语法访问,也可以用KVC。(后面两种纯属实验)

        student.age = 11;
        int age1 = student.age;
        NSLog(@"%d",age1);
        
        [student setValue:@"22" forKey:@"age"];
        NSString *age2 = [student valueForKey:@"age"];
        NSLog(@"age2:%@",age2);
        
        [student setValue:@"33" forKey:@"_age"];
        NSString *age3 = [student valueForKey:@"_age"];
        NSLog(@"age3:%@",age3);

运行结果:

2016-03-10 17:34:53.829 KVC[9591:400420] 11

2016-03-10 17:34:53.829 KVC[9591:400420] age2:22

2016-03-10 17:34:53.829 KVC[9591:400420] age3:33

当然了,在.m里,匿名类中定义的属性和成员变量都可以通过KVC的方式进行访问。

4)实际应用例子,修改UISearchBar的placeHolder字体颜色:

//修改placeholder的颜色
    UITextField *searchField = [_searchBar valueForKey:@"_searchField"];
    [searchField setValue:RGBACOLOR(184, 184, 186, 1) forKeyPath:@"_placeholderLabel.textColor"];

通过这种方式可以修改很多系统控件。

二、键路径访问属性

如果访问这个类里中的属性中的属性呢?那就用到了键路径 

关键字:键路径取值valueForKeyPath 键路径存值:forKeyPath

1) 新建一个类Course,课程类,课程类有课程名称这个属性

.h

@interface Course : NSObject
{
    NSString *CourseName;
}
@end

.m

#import "Course.h"

@implementation Course

@end

2) 在Student中添加Course属性 ,student.h文件中代码如下:

#import "Course.h"
@interface Student : NSObject
{
    NSString *name;
    Course *course;
}

.m没有改动

3)

在main方法中,我们实验通过键路径访问Course中CourseName的属性

        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);

运行结果正确^_^

三、自动封装基本数据类型

1)我们在Student类中添加分数属性 NSInteger point;.m不变,然后进行存取。

2)上面的age属性已经展示了,我们用NSString*类型设置的属性值@"22",而我们的属性是int类型的,存取都没有问题。

 

 四、操作集合

这个看起来比较高端。在Student类中加入数组NSArray,用来表示其他的学生。这样我们可以添加多个其他的学生,再用集合操作计算学生的分数,最高分,最低分,平均分,求和等。

 

 //操作集合
        Student *student1 = [[Student alloc]init];
        Student *student2 = [[Student alloc]init];
        Student *student3 = [[Student alloc]init];
        [student1 setValue:@"59" forKey:@"point"];
        [student2 setValue:@"20" forKey:@"point"];
        [student3 setValue:@"100" forKey:@"point"];
        NSArray *array = @[student1,student2,student3];
        [student setValue:array forKey:@"otherStudent"];
        NSLog(@"其他学生的成绩%@", [student valueForKeyPath:@"otherStudent.point"]);
        NSLog(@"共%@个学生", [student valueForKeyPath:@"otherStudent.@count"]);
        NSLog(@"最高成绩:%@", [student valueForKeyPath:@"otherStudent.@max.point"]);
        NSLog(@"最低成绩:%@", [student valueForKeyPath:@"otherStudent.@min.point"]);
        NSLog(@"平均成绩:%@", [student valueForKeyPath:@"otherStudent.@avg.point"]);
        NSLog(@"总成绩:%@", [student valueForKeyPath:@"otherStudent.@sum.point"]);

 

 运行结果:

2016-03-10 18:41:19.293 KVC[10313:439192] 其他学生的成绩(

    59,

    20,

    100

)

2016-03-10 18:41:19.293 KVC[10313:439192] 3个学生

2016-03-10 18:41:19.294 KVC[10313:439192] 最高成绩:100

2016-03-10 18:41:19.294 KVC[10313:439192] 最低成绩:20

2016-03-10 18:41:19.294 KVC[10313:439192] 平均成绩:59.666666666666666666666666666666666666

2016-03-10 18:41:19.294 KVC[10313:439192] 总成绩:179