#pragma mark - view life cycle
- (void)viewDidLoad
{
[super viewDidLoad];
// KVO\KVC example
// KVC
// KVC是KeyValueCoding的简称,它是一种可以直接通过字符串的名字(key)来访问类属性的机制。而不是通过调用Setter、Getter方法访问。
// 当使用KVO、Core Data、CocoaBindings、AppleScript(Mac支持)时,KVC是关键技术;
// KVC的获取值方法:
// valueForKey:传入NSString属性的名字;
// valueForKeyPath:传入NSString属性的路径,xx.xx形式;
// valueForUndefinedKey它的默认实现是抛出异常,可以重写这个函数做错误处理;
// KVC的修改值方法:
// setValue:forKey:
// setValue:forKeyPath:
// setValue:forUndefinedKey:
// setNilValueForKey: 当对非类对象属性设置nil时,调用,默认抛出异常。
// 一对多关系成员的情况
// mutableArrayValueForKey:有序一对多关系成员 NSArray
// mutableSetValueForKey:无序一对多关系成员 NSSet
// KVO
// KVO 的作用,它通过key path观察对象的值,当值发生变化的时候会收到通知;
// valueforkey和objectforkey区别:
// objectforkey是NSDictionary的方法,valueforkey是KVC的方法,两者都是键值对应,区别是valueforkey只允许使用NSString类型,objectforkey可以是任意类型;
// 同理valueforkeyPath、setValue:forkey等也是kvc的方法;
self.curUser = [[UserInfo_M alloc] init];
// 如果rmarkName这个key对应的是一个对象且想要用kvc的方法对对象中的某一property赋值,可以用setValue:forKeyPath方法
// 如[self.curUser setValue:@"zyxiao" forKey:@"remarkName.firstname"],同self.curUser.remarkName.firstname = @"zyxiao"
// 不过要注意一点,在如此操作的时候要确保这个remarkName在赋值的时候已经实例化;
[self.curUser setValue:@"zyxiao" forKey:@"remarkName"];
// [self.curUser setValue:@"zyxiao" forKeyPath:@"remarkName"];// 效果同上
// self.curUser.remarkName = @"zyxiao"; // 效果同上
// 设置控制器对象为curUser属性的观察者,观察curUser属性中的remarkName属性的变化
[self.curUser addObserver:self forKeyPath:@"remarkName" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL]; // 添加观察者
self.testLabel.text = [self.curUser valueForKey:@"remarkName"];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc
{
// 移除观察者
// 注意:添加观察者与移除观察者要成对出现;
[self.curUser removeObserver:self forKeyPath:@"remarkName" context:NULL];
}
#pragma mark - Actions
// 由按钮触发remarkName属性的变化
- (IBAction)buttonClicked:(id)sender
{
[self.curUser setValue:@"tiancai" forKey:@"remarkName"];
// self.curUser.remarkName = @"tiancai"; // 效果同上
// [self.curUser changeRemarkName]; // 注意:不通过setter或setValue方法修改属性的值是不会产生通知的;
}
#pragma mark - NSKeyValueCoding Protocol
// 通知回调方法
- (void)observeva lueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"keyPath:%@",keyPath);
if ([keyPath isEqualToString:@"remarkName"]) {
self.testLabel.text = [self.curUser valueForKey:@"remarkName"];
}
}