• KVC/KVO之暴力的KVC


    本章将分为三个部分:

    • KVC是什么
    • KVC之Set/Get
    • KVC键值路径之Set/Get

    KVC是什么

    KVC,即 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性,并不需要调用setter/getter函数或者类的实例变量。

    KVC之Set/Get

    类A中有3个变量,都是private权限,关于访问权限的,请参见《Objective-C 成员变量

    A.h

    @interface A : NSObject
    {
    @private
        NSString *str;
        NSInteger value;  //注意这里没星号哦哦哦
        NSArray *array;
    }
    @end

    A.m:重写Description函数,用于NSLog

    @implementation A
    /**
     *    重写Description方法,可用于NSLog打印
     */
    - (NSString *)description
    {
        return [NSString stringWithFormat:@"
    %@
    %li
    %@", str, (long)value, array];
    }
    @end

    Main.m:理论上来说,外部变量是访问不到这3个私有变量的,但是暴力的KVC来了。

    A *a = [[A alloc] init];
    
    //KVC之set
    [a setValue:@"HelloWorld" forKey:@"str"];
    [a setValue:@2015 forKey:@"value"];
    [a setValue:@[@"HearthStone", @2] forKey:@"array"];
    
    NSLog(@"%@", a);
    
    //KVC之get
    NSString *str = [a valueForKey:@"str"];
    NSInteger value = [[a valueForKey:@"value"] integerValue];  //id 转为 NSInteger
    NSArray *array = [a valueForKey:@"array"];
    
    NSLog(@"
    %@
    %ld
    %@", str, (long)value, array);

    输出为

    HelloWorld
    2015
    (
    HearthStone,
    2
    )

    HelloWorld
    2015
    (
    HearthStone,
    2
    )

    分析:

    KVC的Set方法(重点)

    [a setValue:@"HelloWorld" forKey:@"str"];

    是KVC的set方法,其中key一定要为消息接收者的属性名称,而不能是自定义的。

    KVC的Get方法(重点)

    NSString *str = [a valueForKey:@"str"];

    是KVC的get方法,其中key一定要为消息接收者的属性名称,而不能是自定义的。

    当Set方法遇到基本数据类型

    [a setValue:@2015 forKey:@"value"];

    NSInteger是基本数据类型,设置基本数据类型的时候,需要将基本类型转化成NSNumber,在设置值的时候,系统会有自动解包的过程,NSNumber会解包赋值给value.

    当Get方法遇到基本数据类型

    NSInteger value = [[a valueForKey:@"value"] integerValue];  //id 转为 NSInteger

    valueForKey返回的是id类型,id转换为NSInteger的方法应该是上面这种,而下面这种写法是错误的!

    NSInteger value = (NSInteger)[a valueForKey:@"value"];

    题外话:重写Description来方便NSLog的输出

    - (NSString *)description
    {
        return [NSString stringWithFormat:@"
    %@
    %li
    %@", str, (long)value, array];
    }
    
    NSLog(@"%@", a);

    将打印出

    HelloWorld
    2015
    (
    HearthStone,
    2
    )

    KVC键值路径之Set/Get

    假如A含有一个类B,那么如何通过KVC拿到B的属性呢?答案是使用键值路径。

    A.h

    @interface A : NSObject
    {
    @private
        NSString *str;
        NSInteger value;  //注意这里没星号哦哦哦
        NSArray *array;
        B *b;
    }
    @end

    B.h

    @interface B : NSObject
    {
    @private
        NSinteger *age;
    }
    @end

    现在,假如A的array里面装的都是B(装B--)

    Main.m

    A *a = [[A alloc] init];
    ...//set Object
    [a setValue:@23 forKeyPath:@"b.age"];
    
    NSArray *array = [a valueForKeyPath:@"array.age"];        //返回了数组中所有B的age
    NSInteger count = [a valueForKeyPath:@"array.@count"];    //返回了数组中B的个数
    NSInteger maxAge = [a valueForKeyPath:@"array.@max.age"]; //返回了数组中B的age最大的
    NSInteger sumAge = [a valueForKeyPath:@"array.@sum.age"]; //返回了数组中B的age和
    NSInteger avgAge = [a valueForKeyPath:@"array.@avg.age"]; //返回了数组中B的age平均值

    键值路径可以用来访问不是基本类型的实例变量的属性,也可以快速取到数组中的对象的同一个属性,同时可以利用@count @max @sum @avg等进行计算。

    KVC的键值路径的Set方法(重点)

    [a setValue:@23 forKeyPath:@"b.age"];

    KVC的键值路径的Get方法(重点)

    NSArray *array = [a valueForKeyPath:@"array.age"];        //返回了数组中所有B的age
  • 相关阅读:
    stringstream用法
    来到上海了
    [转]强悍!情书居然能写得如此专业
    asp.net控件开发基础(23)
    当你遇到internal的时候
    asp.net控件设计时支持(3)
    asp.net控件设计时支持(5)
    CS中的缓存类,保证都看的懂
    快要毕业了
    asp.net控件设计时支持(4)
  • 原文地址:https://www.cnblogs.com/chenyg32/p/4803795.html
Copyright © 2020-2023  润新知