您的位置:首页 > 移动开发 > Objective-C

Objective-C:KVC机制

2015-10-14 21:40 417 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: