• Objective


    KVC的使用


    1、KVC 全称 key valued coding 键值编码

    反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性.JAVA,C#都有这个机制。ObjC也有,所以你根部不必进行任何操作就可以进行属性的动态读写,就是KVC。

    KVC的操作方法由NSKeyValueCoding提供,而他是NSObject的类别,也就是说ObjC中几乎所有的对象都支持KVC操作。

    2、常用方法

    获取值的方法

    valueForKey:,传入NSString属性的名字。

    valueForKeyPath:,传入NSString属性的路径,xx.xx形式。

    valueForUndefinedKey它的默认实现是抛出异常,可以重写这个函数做错误处理。

    那么问题来了 现在有连个类,Book类(对应属性:name,prices)和Person类(对应属性:name,height,Book *book),person有一本名字叫做《太阳的后裔》,那么现在想通过KVC给这本书赋值,应该如何操作?

    个人总结答案:因为现在想修改的不是对应类也就是Person类的属性,是要修改Book的属性(person.book),所以需要通过valueForKeyPath来进行修改^_^                     

                                   


    修改值的方法

    setValue:forKey:

    setValue:forKeyPath:

    setValue:forUndefinedKey:

     setValue:forKey的搜索过程:

    1. 用@property定义的属性的key值(这里指的是property 系统生成的setter、getter方法 )
    2. setter方法的key值(用户自定义的setter方法)
    3. 直接访问成员变量,先找key,如果找不到,再找_key
    4. 以上三种都未找到就会调用- (void)setValue:(id)value forUndefinedKey:(NSString *)key 方法。
    5. 如果没有重写setValue:forUndefinedKey程序会马上崩溃。

    注意:

    1、使用KVC间接修改对象属性时,系统会自动判断对象属性的类型,并完成转换。

    2、KVC可以访问成员变量,无论是否提供getter/setter方法,无论可见性是怎样,是否有readonly修饰。

     setValue:forUndefinedKey与valueForUndefinedKey的应用

    KVC的主要用途无非是ORM映射,就是将dictionary转换成model,但有些服务器返回的字段有可能是oc的关键字比如‘id’,’description’等。如上代码举得id的例子,我们无法让@property后面key值为id,于是使用大写的ID代替,KVC是区分大小写的我们不用担心。这时我们只需在setValue:forUndefinedKey把id的key值赋值给ID的key值,就可以避免关键字的尴尬。 

    3、dict <->model 互转

    字典转模型

    [self setValuesForKeysWithDictionary:dict];

    模型转字典

    [p dictionaryWithValuesForKeys:array];

    4、KVC集合

    NSArray/NSSet等都支持KVC

    [array valueForKeyPath:@"dog.name"];

    5、使用KVC计算属性

    格式为:[p valueForKeyPath:@"Left keypath部分.@Collectionoperator部分.Right keypath部分”];

    Left keypath部分:需要操作对象路径。

    Collectionoperator部分:通过@符号确定使用的集合操作。

    Right keypath部分:需要进行集合操作的属性。

    举例:[p valueForKeyPath:@"books.@sum.price"];

    @avg:平均值

    @count:总数

    @max:最大

    @min:最小

    @sum:总数

    6、具体代码与实际编辑

    1)当使用KVC给对象的属性赋值时,当根据输入的Key值没有找到对应的Value时调用

    1 - (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    2     
    3     NSLog(@"key = %@没有找到",key);
    4     
    5 }

    2)当找到了对应的key值,代码为

     1 //
     2 //  main.m
     3 //  KVC熟悉与加强
     4 //
     5 //  Created by ma c on 16/5/16.
     6 //  Copyright © 2016年 彭盛凇. All rights reserved.
     7 //
     8 
     9 #import <Foundation/Foundation.h>
    10 
    11 #import "Model.h"
    12 
    13 int main(int argc, const char * argv[]) {
    14     @autoreleasepool {
    15         
    16         Model *model =  [[Model alloc] init];
    17         
    18         [model setValue:@"Coder丶PSS" forKey:@"name"];
    19         [model setValue:@"178" forKeyPath:@"height"];
    20         
    21 //        NSLog(@"%@",model);
    22         
    23         NSLog(@"名字叫%@,身高为%@",[model valueForKey:@"name"],[model valueForKey:@"height"]);
    24         
    25         
    26         
    27     }
    28     return 0;
    29 }

    结果为:

    3)使用原生方法解析数据

    因为本人没有服务器,写了个假数据(plist),进行解析,效果是一样的

    (1)plist:

    (2)解析数据代码

     model.m

     1 //
     2 //  Model.h
     3 //  KVC熟悉与加强
     4 //
     5 //  Created by ma c on 16/5/16.
     6 //  Copyright © 2016年 彭盛凇. All rights reserved.
     7 //
     8 
     9 #import <Foundation/Foundation.h>
    10 
    11 @interface Model : NSObject
    12 
    13 @property (nonatomic, copy, readonly) NSString *name;
    14 
    15 @property (nonatomic, assign, readonly) NSInteger height;
    16 
    17 + (NSArray *)loadData;
    18 
    19 @end

    model.h

     1 //
     2 //  Model.m
     3 //  KVC熟悉与加强
     4 //
     5 //  Created by ma c on 16/5/16.
     6 //  Copyright © 2016年 彭盛凇. All rights reserved.
     7 //
     8 
     9 #import "Model.h"
    10 
    11 @implementation Model
    12 
    13 - (NSString *)description
    14 {
    15     return [NSString stringWithFormat:@"model.name = %@, mdoel.height = %@", _name, @(_height)];
    16 }
    17 
    18 - (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    19     
    20     NSLog(@"key = %@没有找到",key);
    21     
    22 }
    23 
    24 + (NSArray *)loadData {
    25     
    26     //获取plist文件路径
    27     NSString *path = @"/Users/mac/Desktop/KVC熟悉与加强/KVC熟悉与加强/CoderPSS.plist";
    28     
    29     //获取plist文件中的数组
    30     NSArray *array = [NSArray arrayWithContentsOfFile:path];
    31     
    32     //初始化可变数组
    33     NSMutableArray *dataList = [NSMutableArray array];
    34     
    35     //使用字典遍历plist中的数组
    36     for (NSDictionary *dict in array) {
    37         
    38         //初始化model类
    39         Model *model = [[Model alloc] init];
    40         
    41         //使用KVC(setValuesForKeysWithDictionary)方法解析数据
    42         [model setValuesForKeysWithDictionary:dict];
    43         
    44         //将model类加到可变数组
    45         [dataList addObject:model];
    46     }
    47     
    48     //返回可变数组
    49     return dataList;
    50 }
    51 
    52 @end

    运行结果

  • 相关阅读:
    LeetCode 1122. Relative Sort Array (数组的相对排序)
    LeetCode 46. Permutations (全排列)
    LeetCode 47. Permutations II (全排列 II)
    LeetCode 77. Combinations (组合)
    LeetCode 1005. Maximize Sum Of Array After K Negations (K 次取反后最大化的数组和)
    LeetCode 922. Sort Array By Parity II (按奇偶排序数组 II)
    LeetCode 1219. Path with Maximum Gold (黄金矿工)
    LeetCode 1029. Two City Scheduling (两地调度)
    LeetCode 392. Is Subsequence (判断子序列)
    写程序判断系统是大端序还是小端序
  • 原文地址:https://www.cnblogs.com/PSSSCode/p/5499510.html
Copyright © 2020-2023  润新知