现在的位置: 首页 > 综合 > 正文

IOS应用开发-KVC/KVO

2018年07月29日 ⁄ 综合 ⁄ 共 2248字 ⁄ 字号 评论关闭
#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"];
    }
}

抱歉!评论已关闭.