zoukankan      html  css  js  c++  java
  • Objective-C:KVC机制

    KVC:key value coding    键值对的编码

    功能:用来给对象属性设置值或者取出对象属性的值。虽然getter和setter方法也是该功能,但是如果类中没有设置属性特性或者重写这两个方法时,就无法存取属性值了。此时,采用KVC机制可以帮助完成这些要求。
     
    先来个举例:给对象属性设值和取值
    @interface Person
    @property(strong,nonatomic)NSString name;
    @end
    一般模式:
    Perosn *person = [[Person alloc]init];
    [person setName:@“Tom”];
    NSString *name = [person name];
     
    KVC机制:
    [perosn setValue:@“Tom” forKey:@“name”];
    NSString *name = [person valueForKey:@“name”];
     
    详细介绍:

    @interface NSObject(NSKeyValueCoding)

    //默认返回yes,如果没有setter方法,按_key,is_key,key,iskey的顺序搜索成员名

    + (BOOL)accessInstanceVariablesDirectly;

     

    //通过属性的字符串键获取值

    - (id)valueForKey:(NSString *)key;

    //通过属性的字符串键设置值

    -(void)setValue:(id)value forKey:(NSString*)key;

     

    //通过属性路径字符串键获取值(格式:@“_xx._xx")

    - (id)valueForKeyPath:(NSString *)keyPath;

    //通过属性路径字符串键设置属性值(格式:@“_xx._xx")

    - (void)setValue:(id)value forKeyPath:(NSString *)keyPath;

     

    //通过属性字符串键检查值的正确性

    - (BOOL)validateValue:(inout id *)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;

    //通过属性路径字符串键检查值的正确性

    - (BOOL)validateValue:(inout id *)ioValue forKeyPath:(NSString *)inKeyPath error:(out NSError**)outError;

     

    //通过属性数组键返回可变数组(有序一对多的关系:NSArray)

    - (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;

    //通过属性数组路径键返回可变数组(有序一对多的关系:NSArray)

    - (NSMutableArray *)mutableArrayValueForKeyPath:(NSString *)keyPath;

     

    //通过属性集合键返回可变集合(无序一对多的关系:NSSet)

    - (NSMutableSet *)mutableSetValueForKey:(NSString *)key;

    //通过属性集合路径键返回可变集合(无序一对多的关系:NSSet)

    - (NSMutableSet *)mutableSetValueForKeyPath:(NSString *)keyPath;

    //通过数组(多个值)键获取字典值

    - (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;

    //通过字典键设置多个值(数组)

    - (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;

    //通过属性字符串键返回可变有序集合

    - (NSMutableOrderedSet *)mutableOrderedSetValueForKey:(NSString *)key;

    //通过属性路径字符串键返回可变有序集合

    - (NSMutableOrderedSet *)mutableOrderedSetValueForKeyPath:(NSString *)keyPath;

     

     //当key不存在时,会处理异常,即会调用下面这两个方法(例如判断key==id时可以设取值)

    - (id)valueForUndefinedKey:(NSString *)key;

    - (void)setValue:(id)value forUndefinedKey:(NSString *)key;

     

    //为nil设置一个合理的值,对于标量来说,多数情况下合理值为0

    - (void)setNilValueForKey:(NSString *)key;

    @end

     

    @interface NSArray(NSKeyValueCoding)               //不可变数组

    - (id)valueForKey:(NSString *)key;

    - (void)setValue:(id)value forKey:(NSString *)key;    

    @end

      

    @interface NSDictionary(NSKeyValueCoding)          //不可变字典

    - (id)valueForKey:(NSString *)key;

    @end

     

    @interface NSMutableDictionary(NSKeyValueCoding)//可变字典

    - (void)setValue:(id)value forKey:(NSString *)key;

    @end

     

    @interface NSOrderedSet(NSKeyValueCoding)       //有序set集合

    - (id)valueForKey:(NSString *)key ;

    - (void)setValue:(id)value forKey:(NSString *)key ;

    @end

     

    @interface NSSet(NSKeyValueCoding)                 //无序set集合

    - (id)valueForKey:(NSString *)key;

    - (void)setValue:(id)value forKey:(NSString *)key;

    @end

    具体的演示实例如下:

    1、通过键访问属性:

    首先创建一个Person类,perosn.h中声明person对象的属性姓名name,年龄age

    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    {
        NSString *_name;  //姓名
        NSInteger _age;   //年龄
    }
    @end

    person.m中重写输出方法-(NSString*)description

    #import "Person.h"
    
    @implementation Person
    -(NSString *)description
    {
        return [NSString stringWithFormat:@"name:%@,age:%ld",_name,_age];
    }
    @end

    然后再main方法中设置属值性和取出属性值

    #import <Foundation/Foundation.h>
    #import "Person.h"
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool
        {
            //使用KVC来存取对象中的数据成员
            Person *person = [[Person alloc]init];
            
            [person setValue:@"Tom" forKey:@"_name"];
            [person setValue:@23 forKey:@"_age"];
            
            NSLog(@"%@",person);
        }
        return 0;
    }

    打印结果如下:

    2015-10-14 19:49:36.736 Person[5069:267526] name:Tom,age:23
    Program ended with exit code: 0

    2、当对象中的数据成员如果是另一个对象,可以使用keyPath的键路径的形式访问这个对象中的数据成员

    首先创建一个学生类Student,在Student.h中声明学生姓名、年龄、课程对象属性

    #import <Foundation/Foundation.h>
    
    @class Course;
    @interface Student : NSObject
    {
        NSString *_name;
        NSInteger _age;
        Course *_course;   //将课程对象定义为学生对象的属性
    }
    @end

    然后再创建一个课程类Course,在Course.h中声明课程名属性

    #import <Foundation/Foundation.h>
    
    @interface Course : NSObject
    {
        NSString *_CourseName;

          CGFloat _score;  //分数

    }
    @end

    最后再main函数中实现KVC机制

    #import <Foundation/Foundation.h>
    #import "Student.h"
    #import "Course.h"
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool
        {
            
            //创建学生对象
            Student *stu = [[Student alloc]init];
            
            //设置stu属性值
            [stu setValue:@"Tom" forKey:@"_name"];
            [stu setValue:@20 forKey:@"_age"];
            
            //通过键取出属性值
            NSString *name = [stu valueForKey:@"_name"];
            NSInteger age = [[stu valueForKey:@"_age"] integerValue];
            
            NSLog(@"name:%@,age:%ld",name,age);
            
            
            //创建科目对象
            Course *course = [[Course alloc]init];
            
            //通过键设置course属性值
            [course setValue:@"Chinese" forKey:@"_CourseName"];
            [course setValue:@99.3 forKey:@"_score"];
            [stu setValue:course forKey:@"_course"];
            
            //通过键路径取出course属性值
            NSString *courseName = [stu valueForKeyPath:@"_course._CourseName"];
            CGFloat score = [[stu valueForKeyPath:@"_course._score"]floatValue];
            
            NSLog(@"courseName:%@,score:%.1lf",courseName,score);
            
            
            //也可以使用键路径设置和取值
            [stu setValue:@"English" forKeyPath:@"_course._CourseName"];
            courseName = [stu valueForKeyPath:@"_course._CourseName"];
            
            
            //将基本数据类型封装成字符串
            [stu setValue:@"92.5" forKeyPath:@"_course._score"];
            NSString *score2 = [stu valueForKeyPath:@"_course._score"];
            
            NSLog(@"courseName:%@,score2:%@",courseName,score2);
        }
        return 0;
    }

    打印结果如下:

    2015-10-14 20:47:38.412 KVC-键路径[5320:291473] name:Tom,age:20
    2015-10-14 20:47:38.414 KVC-键路径[5320:291473] courseName:Chinese,score:99.3
    2015-10-14 20:47:38.414 KVC-键路径[5320:291473] courseName:English,score2:92.5
    Program ended with exit code: 0

    3、使用KVC操作数组:当对象中有一个数组属性时,也可以使用KVC机制访问数组中的数据

    首先创建一个动物类Animal

    在anmial.h文件中声明属性

    #import <Foundation/Foundation.h>
    
    @interface Animal : NSObject
    {
        NSString *_name;         //名字
        NSString *_food;         //食物
        NSArray *_otherAnimal;   //其他动物数组
    }
    @end

    在animal.m中重写输出方法-(void)description

    #import "Animal.h"
    
    @implementation Animal
    -(NSString*)description
    {
        return [NSString stringWithFormat:@"name:%@,food:%@",_name,_food];
    }
    @end

    在main主函数中进行KVC的操作

    #import <Foundation/Foundation.h>
    #import "Animal.h"
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
           
            //创建动物对象
            Animal *animal = [[Animal alloc]init];
            
            //设置属性
            [animal setValue:@"Cat" forKey:@"_name"];
            [animal setValue:@"fish" forKey:@"_food"];
            
            //取出属性
            NSString *animalName = [animal valueForKey:@"_name"];
            NSString *foodName = [animal valueForKey:@"_food"];
            
            NSLog(@"animalName:%@,foodName:%@",animalName,foodName);
            
            
            //其他的动物
            Animal *animal2 = [[Animal alloc]init];
            Animal *animal3 = [[Animal alloc]init];
            Animal *animal4 = [[Animal alloc]init];
            
            [animal2 setValue:@"dog" forKey:@"_name"];
            [animal3 setValue:@"rabbit" forKey:@"_name"];        
            [animal4 setValue:@"pannada" forKey:@"_name"];
            
            [animal2 setValue:@"gone" forKey:@"_food"];
            [animal3 setValue:@"grass" forKey:@"_food"];
            [animal4 setValue:@"bamboo" forKey:@"_food"];
            
            NSArray *array = @[animal2,animal3,animal4];
            
            [animal setValue:array forKey:@"_otherAnimal"];
            
            //取出其他动物的属性
            NSLog(@"%@",[animal valueForKey:@"_otherAnimal"]); //打印所有动物的所有信息
            NSLog(@"%@",[animal valueForKeyPath:@"_otherAnimal.name"]);//输出所有动物的名字
            NSLog(@"%@",[animal valueForKeyPath:@"_otherAnimal._food"]);//输出所有动物的食物
        }
        return 0;
    }

    打印结果如下:

    2015-10-14 21:31:30.375 KVC-操作数组[5557:308588] animalName:Cat,foodName:fish
    2015-10-14 21:31:30.377 KVC-操作数组[5557:308588] (
        "name:dog,food:gone",
        "name:rabbit,food:grass",
        "name:pannada,food:bamboo"
    )
    2015-10-14 21:31:30.377 KVC-操作数组[5557:308588] (
        dog,
        rabbit,
        pannada
    )
    2015-10-14 21:31:30.377 KVC-操作数组[5557:308588] (
        gone,
        grass,
        bamboo
    )
    Program ended with exit code: 0

     

  • 相关阅读:
    自学Linux命令的四种方法
    linux命令学习
    设计师提高效率必备的10大在线工具
    基于CNN网络的汉字图像字体识别及其原理
    字库的产生
    开篇
    智能建筑系统集成发展目标——节能建筑
    建筑节能案例解析:拜尔的生态幼儿园
    能源管理系统(Synchro EMS)技术架构
    能源管理系统(Synchro EMS)
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/4878982.html
Copyright © 2011-2022 走看看