Objective-C:KVC机制
KVC:key value coding 键值对的编码
@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