zoukankan      html  css  js  c++  java
  • KVC & KVO 入门

    KVC:

    简介:

    全称 Key-Value Coding 。KVC是一种间接访问对象属性(用字符串表征)的机制,而不是直接调用对象的accessor(setter/getter)方法或是直接访问成员对象。KVC的key值必需小写,并且必须是对象内的属性或变量。可以访问一些没有暴露出来的变量。

    使用:

    [_bank setValue:@"I am Lee" forKey:@"name"];   // 设置值
    [_bank valueForKey:@"name"];  //读取值

    可以看出KVC的使用是非常简单的,但是只有KVC是不够的,还需要结合KVO来做。

    KVO:

    简介:

    当指定的对象的属性被修改了,允许对象接受到通知的机制。每次指定的被观察对象的属性被修改的时候,KVO都会自动的去通知相应的观察者。主要使用KVO来实现对象属性和变量的监听。当有属性改变,KVO会提供自动的消息通知。这样的架构有很多好处。首先,开发人员不需要自己去实现这样的方案:每次属性改变了就发送消息通知。这是KVO机制提供的最大的优点。因为这个方案已经被明确定义,获得框架级支持,可以方便地采用。开发人员不需要添加任何代码,不需要设计自己的观察者模型,直接可以在工程里使用。其次,KVO的架构非常的强大,可以很容易的支持多个观察者观察同一个属性,以及相关的值。总的来说,就是不需要自己去定义消息的通知机制,只需关心对象的值的变化。

    使用:

    定义Bank.h文件

    //
    //  Bank.h
    //  testDemo
    //
    //  Created by stardust on 15-1-15.
    //  Copyright (c) 2015年 com. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface Bank : NSObject
    {
        NSString *name;
    }
    @property NSInteger money;
    -(void)beRobbed;
    @end

    Bank.m文件:

    //
    //  Bank.m
    //  testDemo
    //
    //  Created by stardust on 15-1-15.
    //  Copyright (c) 2015年 com. All rights reserved.
    //
    
    #import "Bank.h"
    
    @implementation Bank
    
    //@synthesize money;
    
    -(void)beRobbed{
        self.money = self.money - 100;
    }
    @end

    APerson.h文件:

    //
    //  APeron.h
    //  testDemo
    //
    //  Created by stardust on 15-1-15.
    //  Copyright (c) 2015年 com. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface APeron : NSObject
    
    @end

    APerson.m文件:

    //
    //  APeron.m
    //  testDemo
    //
    //  Created by stardust on 15-1-15.
    //  Copyright (c) 2015年 com. All rights reserved.
    //
    
    #import "APeron.h"
    
    
    @implementation APeron
    
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
        if ([keyPath isEqualToString:@"name"]) {
            NSLog(@"KVC old name is %@ , new name is %@",[change objectForKey:NSKeyValueChangeOldKey],[change objectForKey:NSKeyValueChangeNewKey]);
        }
        else if([keyPath isEqualToString:@"money"]){
            NSLog(@"KVC old money is %@ , new money is %@",[change objectForKey:NSKeyValueChangeOldKey],[change objectForKey:NSKeyValueChangeNewKey]);
        }
        else{
            NSLog(@"KVC old value is %@ , new value is %@",[change objectForKey:NSKeyValueChangeOldKey],[change objectForKey:NSKeyValueChangeNewKey]);  
        }
    }
    
    @end

    主文件KVOController.m:

    //
    //  KVOViewController.m
    //  testDemo
    //
    //  Created by stardust on 15-1-15.
    //  Copyright (c) 2015年 com. All rights reserved.
    //
    
    #import "KVOViewController.h"
    #import "Bank.h"
    #import "APeron.h"
    
    
    @interface KVOViewController ()
    @property APeron *aperson;
    @property Bank *bank;
    @end
    
    @implementation KVOViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        
        _aperson = [[APeron alloc]init];
        _bank = [[Bank alloc]init];
        
        [_bank addObserver:_aperson forKeyPath:@"name" options:(NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew) context:@"hello"];
        [_bank addObserver:_aperson forKeyPath:@"money" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) context:@"hello2"];
        [_bank addObserver:_aperson forKeyPath:@"jack" options:(NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew) context:@"hello3"];
        
        [_bank setValue:@"I am Lee" forKey:@"name"];
        _bank.money = 101;
        [_bank beRobbed];
        
        NSLog(@"... %@",[_bank valueForKey:@"name"]);
        
        //[_bank setValue:@"Tim Jack" forKey:@"jack"];  // 此句报错
        
        

        // 一定要移除kvo,不然会有可能报错

    
    

        [_bank removeObserver:_aperson forKeyPath:@"name"];

    
    

        [_bank removeObserver:_aperson forKeyPath:@"money"];

    
    

        [_bank removeObserver:_aperson forKeyPath:@"jack"];

    
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    /*
    #pragma mark - Navigation
    
    // In a storyboard-based application, you will often want to do a little preparation before navigation
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */
    
    @end

    显示结果:

    2015-01-15 19:36:52.256 testDemo[3442:634253] KVC old name is <null> , new name is I am Lee
    2015-01-15 19:36:52.257 testDemo[3442:634253] KVC old money is 0 , new money is 101
    2015-01-15 19:36:52.257 testDemo[3442:634253] KVC old money is 101 , new money is 1
    2015-01-15 19:36:52.258 testDemo[3442:634253] ... I am Lee

    通过以上可以看出,设置aperson来监听Bank对象的变化,监听变化的处理放在APerson中,只要Bank对象中被监听的值发生变化,无论是直接设置改变,还是通过KVC,都能监听得到并执行相关监听的逻辑。但是,对于不存在的值,例如主文件代码中注释了的这句:” [_bank setValue:@"Tim Jack" forKey:@"jack"];“,即使可以添加不存在值的监听,但是调用相应的KVC时,会crash,这可能跟KVC的机制有关。

    参考:

    1

  • 相关阅读:
    网站微信登录-python 实现
    最终还是迁移到github
    理解 python 装饰器
    Git 学习之 Git Basics
    haskell 常用 函数
    jinja 2 filter 使用
    目标的牵引作用
    姨妈去世了
    OKR的理解
    无法证明的事情,和梦又有什么区别呢
  • 原文地址:https://www.cnblogs.com/starwolf/p/4227168.html
Copyright © 2011-2022 走看看