zoukankan      html  css  js  c++  java
  • (五十一)KVC与KVO详解

    KVC的全称为key value coding,它是一种使用字符串间接更改对象属性的方法。

    假设有一个Person类和一个Student类,其中Person类有age、name两个属性,Student多一个no(学号)属性。

    1.valueForKey: 方法通过传入一个键值返回一个id对象,KVC具有自动包装功能,注意如果是基本类型会返回被包装的对象,需要使用XxxValue方法解包,例如:

    NSLog(@"%d",[[s valueForKey:@"age"] intValue]);
    虽然age属性为int,但是在这个方法下返回的为NSNumber,应该解包再使用。

    2.setValue: forKey: 可以通过key设置Value,对于基本类型应该用NSNumber或者NSValue进行包装(也可以通过@(...)快速包装)。

    [s setValue:@18 forKey:@"age"];

    [s setValue:[NSNumber numberWithInt:18] forKey:@"age"];
    Tip:上面两个方法是非常智能的,会先去寻找getter方法(甚至还会查找isXxx的标准命名方法)或者setter方法,如果找不到就查找_Xxx或者Xxx为名称的成员变量取值或者赋值,总之只要使用规范的命名方法和声明方法,KVC就可以处理。


    3.dictionaryWithValuesForKeys:方法,通过传入key数组,返回一个成员变量名(不加下划线)和变量值的键值对组成的字典。

    NSDictionary *dict = [s dictionaryWithValuesForKeys:[NSArray arrayWithObjects:@"name",@"age", nil]];
    如果使用@来初始化数组,不必写nil(写了会报错,提示nil不是一个OC对象),应该如下书写:

    NSDictionary *dict1 = [s dictionaryWithValuesForKeys:@[@"name",@"age"]];
    打印出的dict值为:

    {
        age = 18;
        name = John;
    }

    4.setValuesForKeysWithDictionnary: 方法,通过传入字典,初始化相应的键对应的成员变量(同前所述,非常智能的查找)的值为相应的的键值,在MVC设计模式中,模型初始化常用这个方法,一般是写在初始化方法中,通过字典初始化模型数据。


    5. dictionaryWithObjects: forKeys: 方法通过传入对象和键名,生成一个 (键-对象) 键值对的字典,注意对非OC对象的包装。


    6.key path称为键路径,如果要跨越一层模型数据访问第二层模型数据,例如学生拥有一个学生卡对象,学生卡内部也是个模型,如果要透过card对象访问卡号no属性,就需要通过card.no来调用set或者get方法,这时候可以使用setValue: forKeyPath: 方法,在KeyPath后传入card.no就可以设置no的值了,同样,使用valueForKeyPath:方法可以得到card.no的值。


    7.假如有一个Group对象拥有一个Student对象数组,如果要获得所有的Student对象的name,可以使用valueForKeyPath方法返回name数组:

        Student *s = [[Student alloc] init];
        s.age = 15;
        s.name = @"John";
        s.no = @"10010";
        Student *s2 = [[Student alloc] init];
        s2.age = 18;
        s2.name = @"Rose";
        s2.no = @"10011";
        
        Group *g = [[Group alloc] init];
        g.persons = @[s,s2];
        
        NSArray *array = [g valueForKeyPath:@"persons.name"];
    通过打印可以发现array内存放的为s和s2的name:

    (
        John,
        Rose
    )


    8.键路径运算:

    @count运算符表示计算一组值的平均值。这里也可以使用路径运算,例如Group.persons的@count结果 和 Group的"persons.@count" 的结果是一样的,可以把@count理解为具有集合特性的对象的一个成员变量,它表示集合中元素的个数

    @sum.xxx 表示计算某个集合内部的xxx属性的和,注意如果是路径访问,使用类似books.@sum.price访问books内部成员的price来求和。


    KVO的全称为key value observing,是一种监听对象属性变化的机制。

    通过 addObserver...方法添加监听器,实现observerValueForKeyPath...来监听,通过removeObserver移除监听器。
    下面演示一个例子,通过KVO监听ViewController类的name属性的变化,通过NSTimer产生随机的字符串赋给name,打印监听函数的输出,注意有监听就要有移除,要重写dealloc方法,注意ARC不要调super的dealloc方法。

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        [self addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
        
        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(changestr) userInfo:nil repeats:YES];
        [timer fire];
        
    }
    
    - (void)changestr{
        self.name = [NSString stringWithFormat:@"%d change",arc4random()];
    }
    
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
        
        NSLog(@"the keyPath : <%@> ofObject : <%@> is change to <%@>",keyPath,object,change);
        
    }
    
    - (void)dealloc{
        
        [self removeObserver:self forKeyPath:@"name"];
        
    }

    打印出的数据为:

    the keyPath : <name> ofObject : <<ViewController: 0x7d18ca00>> is change to <{
        kind = 1;
        new = "1844532638 change";
    }>
    






  • 相关阅读:
    想不明白为什么不复用老接口?
    dubbo入门教程-从零搭建dubbo服务
    使用Node.js时如何引入jQuery
    博客园在我的博客添加点击小心心特效
    博客园在微信内置浏览器打开时添加微信赞赏码功能
    Keepalived
    双网卡服务器使用指定网卡互通不同网段数据
    LNMP详解
    Centos7数据实时同步(Rsync+inotify)
    解决Centos7本机时间与实际时间相差8小时
  • 原文地址:https://www.cnblogs.com/aiwz/p/6154200.html
Copyright © 2011-2022 走看看