标签:
KVC是KeyValue Coding的简称,它是一种可以直接通过字符串的名字(key)来访问类属性的机制。而不是通过调用Setter、Getter方法访问
具体的例子:
1.创建一个people类,继承与NSObject
@interface People : NSObject
@property(nonatomic,copy)NSString *name;//people的属性
@end
当我们在类外访问的时候,可以通过打点调用属性
People *p=[People new];//创建一个people
p.name=@"李四";
也可以通过kvc的方式来调用
People *people=[People new];
[people setValue:@"张三" forKey:@"name"];
NSLog(@"%@",people.name);//张三
NSString *name=[people valueForKey:@"name"];
NSLog(@"%@",name);
你或许说了,打点调用不是可以更加方便吗?可以kvo有一个打点调用不能实现的方法:例如
@interface People : NSObject
{
NSString *_name;
}
@end
_name是people类的全局变量,这样我们就不能进行打点调用了,这时候kvc就派上用场了
People *people=[People new];
[people setValue:@"张三" forKey:@"name"];
NSLog(@"%@",people.name);//张三
NSString *name=[people valueForKey:@"name"];//得到值
NSLog(@"%@",name);//张三
你会发现程序居然没有报错,而且执行成功了
@interface People : NSObject
{
NSString *name;
}
@end
和_name同理
但是我们调用一个不存在的key时,程序就会崩溃
比如我们在程序外调用 [people setValue:@"张三" forKey:@"name1"];
Terminating app due to uncaught exception ‘NSUnknownKeyException‘, reason: ‘[<People 0x106f14270> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key name1.‘ 原因就是因为没有name1这个key值
结果和上面一样:不管结果如果,你都会发先系统调用了属性的get方法,所以总结如下首先会调用set(get)方法如果set(get)方法不存在,会找到_key当_key不存在时,会找到key当key不存在时,会crash。
2.kvc可以根据路径值访问属性和对属性赋值,例如
我们有一个car类,有一个people类
@interface People : NSObject
@property (nonatomic,strong) NSString *name;
@property (nonatomic,strong) NSNumber *age;
@property (nonatomic,strong) Car *car;
@end
@interface Car : NSObject
@property (nonatomic,strong) NSString *name;
@property (nonatomic,strong) UIColor *bgColor;
@end
类外调用:
People *people = [People new];
[people setValue:@"SUV" forKeyPath:@"car.name"];
NSString *carName=[people valueForKey:@"car.name"];//suv
3.可以通过字典对属性赋值:
例如:
@interface People : NSObject
@property (nonatomic,strong) NSString *name;
@property (nonatomic,strong) NSNumber *age;
@end
NSDictionary *dict = @{@"name": @"张三",@"age":@12}
People *people = [People new];
[people setValuesForKeysWithDictionary:dict];
NSLog(@"%@ %d",people.name,people.age);//张三 12
注意事项:如果字典中的键值有id之类的xcode保留值程序就会崩溃,基本数据类行也不识别,解决方法:
//kvc崩溃的话写以下方法
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
if ([key isEqualToString:@"id"]) {//这里的id指的是oc里面的保留字
self.pID = value;
}else if ([key isEqualToString:@"pSex"])
{
//@property (nonatomic,assign) BOOL sex;
self.sex = [value boolValue];//把对象的值改为基本的数据类型
}
NSLog(@"%@ %@",value,key);
}
kvo:全称是Key-value observing,翻译成键值观察。提供了一种当其它对象属性被修改的时候能通知当前对象的机制。再MVC大行其道的Cocoa中,KVO机制很适合实现model和controller类之间的通讯。
不多说:举例说明
创建一个people类
@interface People : NSObject
@property (nonatomic,strong) NSString *name;
@end
给一个person对象添加观察者
[_people addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:@"hello"];//NSKeyValueObservingOptionOld,获得旧的值 NSKeyValueObservingOptionNew:获得新的值
假如我们改变people的name属性,就会触发事件
/*
此方法必须实现,不实现的话系统回报/*
reason: ‘<ViewController: 0x8e06540>: An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
错误
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
/*
keyPath:观察的路径
object:被观察者
change:改变的值
context:对应添加时的context
*/
NSLog(@"%s",__FUNCTION__);
}
标签:
原文地址:http://www.cnblogs.com/hualuoshuijia/p/4998846.html