美文网首页iOS进阶常用类iOS
iOS --- 关于KVC使用的一些小技巧

iOS --- 关于KVC使用的一些小技巧

作者: icetime17 | 来源:发表于2016-07-26 22:20 被阅读1412次

    KVC是iOS开发中经常会用到的技巧, 主要包括valueForKey:/setValue:ForKey:, valueForKeyPath:/setValue:forKeyPath:两队组合方法.
    valueForKey:会首先查找以参数名命名的getter方法, 如果没有找到, 则在对象内寻找名称格式为_key或key的实例变量.
    另外还要dictionaryWithValuesForKeys:/setValuesForKeysWithDictionary方法用于获取或设置指定的内容.

    这里有两个类:

    #pragma mark - Dog
    
    @interface Dog : NSObject
    
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, assign) NSInteger age;
    @property (nonatomic, copy) NSString *city;
    
    @end
    
    @implementation Dog
    
    @end
    
    
    
    #pragma mark - Person
    
    @interface Person : NSObject
    
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, assign) NSInteger age;
    
    @property (nonatomic, strong) Dog *dog;
    
    @property (nonatomic, strong) NSArray<Dog *> *dogs;
    
    @end
    
    @implementation Person
    
    @end
    

    其中, Person类有一个dogs属性. 下面将在这两个类的基础上展示一些小的demo.

    基本使用

    Dog *aDog = [[Dog alloc] init];
    aDog.name = @"My Dog";
    aDog.age = 2;
    NSString *dogName = [aDog valueForKey:@"name"];
    NSInteger dogAge = [[aDog valueForKey:@"age"] integerValue];
    NSLog(@"dogName : %@, dogAge : %ld", dogName, dogAge);
    

    键路径

    Person *aPerson = [[Person alloc] init];
    aPerson.name = @"Chris";
    aPerson.age = 18;
    aPerson.dog = aDog;
    
    NSString *name = [aPerson valueForKeyPath:@"name"];
    NSInteger age = [[aPerson valueForKeyPath:@"age"] integerValue];
    dogName = [aPerson valueForKeyPath:@"dog.name"];
    dogAge = [[aPerson valueForKeyPath:@"dog.age"] integerValue];
    NSLog(@"testKeyPath: name : %@, age : %ld", name, age);
    NSLog(@"testKeyPath: dogName : %@, dogAge : %ld", dogName, dogAge);
    

    注意, 键路径的写法遵循点语法.

    批量操作

    使用KVC, 有时候可以非常方便地进行一些批量的操作.

    Dog *dog1 = [[Dog alloc] init];
    dog1.name = @"Dog 1";
    dog1.age = 1;
    dog1.city = @"Shanghai";
    
    Dog *dog2 = [[Dog alloc] init];
    dog2.name = @"Dog 2";
    dog2.age = 2;
    dog2.city = @"Shanghai";
    
    Dog *dog3 = [[Dog alloc] init];
    dog3.name = @"Dog 3";
    dog3.age = 3;
    dog3.city = @"Beijing";
    
    Person *aPerson = [[Person alloc] init];
    aPerson.name = @"Chris";
    aPerson.age = 18;
    aPerson.dogs = @[dog1, dog2, dog3];
    

    测试代码如下:

    NSArray *dogNames = [aPerson valueForKeyPath:@"dogs.name"];
    NSArray *dogAges = [aPerson valueForKeyPath:@"dogs.age"];
    NSMutableString *str = [[NSMutableString alloc] init];
    [str appendString:@"dogNames :"];
    for (NSInteger i = 0; i < dogNames.count; i++) {
        [str appendFormat:@" %@, %ld years old. ", dogNames[i], [dogAges[i] integerValue]];
    }
    

    NSArray实现valueForKeyPath:的方法是循环遍历它的内容并向每个对象发送消息.

    批量修改如下:

    [aPerson setValue:@"Xiamen" forKeyPath:@"dogs.city"];
    
    cities = [aPerson valueForKeyPath:@"dogs.@distinctUnionOfObjects.city"];
    NSLog(@"cities : %@", cities);
    

    快速运算

    使用KVC进行快速运算的键路径语法类似于 *** dogs.@count *** , *** dogs.@sum.age *** 等.

    // dogs表示取出内容, @count即进行计算, 通知KVC机制进行键路径左侧值的对象总数
    NSNumber *countOfDogs = [aPerson valueForKeyPath:@"dogs.@count"];
    NSLog(@"count of dogs : %@", countOfDogs);
    
    // 获取@sum左侧的集合, 对集合中的每个对象执行右侧操作age, 将结果组成一个集合并返回.
    NSNumber *ageCountOfDogs = [aPerson valueForKeyPath:@"dogs.@sum.age"];
    NSLog(@"ageCountOfDogs of dogs : %@", ageCountOfDogs);
    
    NSNumber *ageAvgOfDogs = [aPerson valueForKeyPath:@"dogs.@avg.age"];
    NSLog(@"age avg of dogs : %@", ageAvgOfDogs);
    NSLog(@"age min : %@, max : %@", [aPerson valueForKeyPath:@"dogs.@min.age"], [aPerson valueForKeyPath:@"dogs.@max.age"]);
    
    // 获取唯一值
    NSArray *cities = [aPerson valueForKeyPath:@"dogs.@distinctUnionOfObjects.city"];
    NSLog(@"cities : %@", cities);
    

    这里就不作过多描述.

    dictionaryWithValuesForKeys:/setValuesForKeysWithDictionary:

    直接看代码更直观:

    // 根据设置的key, 来进行组合结果.
    Dog *lastDog = [[aPerson valueForKeyPath:@"dogs"] lastObject];
    NSArray *keys = @[@"name"];
    NSDictionary *values = [lastDog dictionaryWithValuesForKeys:keys];
    NSLog(@"values : %@", values);
    
    // 使用setValuesForKeysWithDictionary根据字典对Dog进行修改
    NSDictionary *newValues = @{@"name": @"My Dog"};
    [lastDog setValuesForKeysWithDictionary:newValues];
    values = [lastDog dictionaryWithValuesForKeys:keys];
    NSLog(@"values : %@", values);
    

    Demo

    Demo请参考:
    DemoKVC
    需要注意的是:
    *** 不要滥用KVC, KVC需要解析字符串来计算需要的结果, 因此速度较慢. 且无法进行错误检查. ***

    相关文章

      网友评论

        本文标题:iOS --- 关于KVC使用的一些小技巧

        本文链接:https://www.haomeiwen.com/subject/tpfojttx.html