#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)observeValueForKeyPath:(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"]; } }
原文:http://blog.csdn.net/zyx586/article/details/19113317