zoukankan      html  css  js  c++  java
  • 梳理一下KVC

      对于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

     

  • 相关阅读:
    JS绑定种类汇总
    JS的块级作用域
    JS中的几种函数
    区分词法作用域(js)与动态作用域(精!)
    JS Dom节点操作demo!
    JS作用域相关知识(#精)
    js解析器(重要!)
    JS之鼠标在盒子中的位置
    JS之鼠标跟随
    JS之事件对象体验
  • 原文地址:https://www.cnblogs.com/lilufeng/p/5263020.html
Copyright © 2011-2022 走看看