zoukankan      html  css  js  c++  java
  • OC——关于KVC

    我们知道在C#中可以通过反射读写一个对象的属性,有时候这种方式特别方便,因为你可以利用字符串的方式去动态控制一个对象。其实由于ObjC的语言特性,你根部不必进行任何操作就可以进行属性的动态读写,这种方式就是Key Value Coding(简称KVC)。

    KVC的操作方法由NSKeyValueCoding协议提供,而NSObject就实现了这个协议,也就是说ObjC中几乎所有的对象都支持KVC操作,常用的KVC操作方法如下:

    • 动态设置: setValue:属性值 forKey:属性名(用于简单路径)setValue:属性值 forKeyPath:属性路径(用于复合路径,例如Person有一个Account类型的属性,那么person.account就是一个复合属性) 
    • 动态读取: valueForKey:属性名 valueForKeyPath:属性名(用于复合路径)
    1 Person *person1=[[Person alloc]init];
    2 //动态设置
    3 [person1 setValue:@"1111" forKey:@"name"];//简单路径
    4 [person1 setValue:@100000000.0 forKeyPath:@"account.balance"];//复合路径
    5 
    6 //动态读取
    7 [person1 valueForKey:@"name" ]//简单路径
    8 [person1 valueForKeyPath:@"account.balance"]//复合路径

    注:即便对象属性是非字符串你依然可以使用字符串赋值,KVC就是这么霸气。。

    从Dictionary来生成对象

    setValuesForKeysWithDictionary, 会为我们把和dictionary的key名字相同的class proerty设置上dict中key对应的value,请注意,你的Dictionary的Key一定一定要和你的类的属性名完全一致。

    1 -(id) initWithDictionary:(NSMutableDictionary*) jsonObject 
    2 { 
    3     if((self = [super init])) 
    4     { 
    5         [self init]; 
    6         [self setValuesForKeysWithDictionary:jsonObject]; 
    7     } 
    8     return self; 
    9 } 

    如果真的有一些特殊情况使你的Dictionary和你的类的属性肯定有不一样的属性名,那么我们可以重写setValue:(id)value forUndefinedKey:(NSString *)key 方法

    1 - (void)setValue:(id)value forUndefinedKey:(NSString *)key 
    2 { 
    3     if([key isEqualToString:@"nameXXX"]) 
    4         self.name = value; 
    5     if([key isEqualToString:@"ageXXX"]) 
    6         self.age = value; 
    7     else 
    8         [super setValue:value forKey:key]; 
    9 } 

    所以只要重载这个方法,就可以处理了那些无法跟property相匹配的key了,默认的实现是抛出一个NSUndefinedKeyException

    如果 这时候server返回的People有了内嵌的json(如Products{product1{count:xx, sumPrice:xx}}, product2{} ….),又该怎么办,能把这个内嵌的json转化成我们的客户端的Product类嘛, 当然可以这时候就需要重载setValue:forKey, 单独处理”Products”这个key, 把它wrapper成我们需要的class

     1 -(void) setValue:(id)value forKey:(NSString *)key 
     2 { 
     3   if([key isEqualToString:@"products"]) 
     4   { 
     5     for(NSMutableDictionary *productDict in value) 
     6     { 
     7       Prodcut *product = [[Product alloc] initWithDictionary:prodcutDict]; 
     8       [self.products addObject:product]; 
     9     } 
    10   } 
    11 } 

    一些其他的使用场景

    例如我们需要把一个数组里的People的名字的首字母大写,并且把新的名字存入新的数组, 这时候通常做法会是遍历整个数组,然后把每个People的name取出来,调用 capitalizedString 然后把新的String加入新的数组中。 有了KVC就有了新做法:
    1 [array valueForKeyPath:@"name.capitalizedString"] 
    我们看到valueForKeyPath, 为什么用valueForKeyPath, 不用valueForKey, 因为valueForKeyPath可以传递关系,例如这里是每个People的name property的String的capitalizedString property, 而valueForKey不能传递这样的关系,所以对于dict里面的dict, 我们也只能用valueForKeyPath。这里我们也看到KVC对于array(set), 做了特殊处理,不是简单操作collection上,而是 针对这些collection里面的元素进行操作,同样KVC也提供更多地操作,例如@sum这些针对collection,有兴趣的同学可以去用下。
     
    还有一些其他情况,未完待续
  • 相关阅读:
    JSP 编码解说
    window系统之mongoDB安装,启动及如何设置为windows服务(总结)
    operator 安装
    JavaScript学习2
    JavaScript学习3
    win7的便签很好使
    COM技术内幕第九章笔记编程工作的简化
    VS乱码之UTF8篇
    必须而不是推荐尽量使用const引用参数
    查看不到网络连接(可以上网)
  • 原文地址:https://www.cnblogs.com/zhangjingyangjinjin/p/4633879.html
Copyright © 2011-2022 走看看