1. KVC简介

    KVC(Key Value Coding)也就是所谓的键/值编码,键/值编码中的基本调用是-ValueForKye:和-setValue:forKey:。

    例子:定义个Student类,Student.h头文件如下:

#import <Foundation/Foundation.h>

// 学生类
@interface Student : NSObject
{
    NSString *name;
    int      age;
}

@end

    Student.m实现文件如下

#import "Student.h"

@implementation Student

- (NSString *)description
{
    return [NSString stringWithFormat:@"姓名:%@,年龄:%d", name,age];
}
@end

name 和age属性没有添加getter和setter方法,通过KVC来设置属性值

main.m代码如下:

#import <Foundation/Foundation.h>
#import "Student.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        Student *student1 = [[Student alloc] init];
        [student1 setValue:@"lily" forKey:@"name"];
        [student1 setValue:[NSNumber numberWithInt:20] forKey:@"age"];
        NSLog(@"%@",student1);
        
        NSLog(@"学生年龄为:%@",[student1 valueForKey:@"age"]);
    }
    return 0;
}

输出结果如下:

wKiom1Po6fSj7dUFAACiXzr8Q6c816.jpg从结果可以看到我们成功的修改了name和age的属性值,但是有一点需要注意,age是一个int值,而不是对象,对于KVC,cocoa自动放入和取出标量值,当我们调用-setValue:forKey:时它自动将标量值从对象中取出,然后赋值给age,当我们调用-valueForKey:时它将标量值自动放入NSNumber或者NSValue中。

2.键路径

键值编码还支持指定键路径

新添加一个班级Grade类,一个班级会有多名学生用NSMutableArray* students来表示,Grade.h头文件如下:

#import <Foundation/Foundation.h>

// 班级类
@interface Grade : NSObject
{
    NSString *name;
    NSMutableArray *students;
}
@property(nonatomic,copy)NSString* name;
@property(nonatomic, retain)NSMutableArray* students;

@end

Grade.m实现如下:

#import "Grade.h"

@implementation Grade
@synthesize name;
@synthesize students;

- (NSString *)description
{
    NSMutableString *str = [[NSMutableString alloc] init];
    [str appendFormat:@"班级名:%@\n",name];
    [str appendString:@"学生列表:\n"];
    for (id obj in students) {
        [str appendFormat:@"%@\n",obj];
    }
    return str;
}

@end

main.m如下:

#import <Foundation/Foundation.h>
#import "Student.h"
#import "Grade.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        Student *student1 = [[Student alloc] init];
        [student1 setValue:@"lily" forKey:@"name"];
        [student1 setValue:[NSNumber numberWithInt:20] forKey:@"age"];
        NSLog(@"%@",student1);
        
        NSLog(@"学生年龄为:%@",[student1 valueForKey:@"age"]);
        
        Student *student2 = [[Student alloc] init];
        [student2 setValue:@"lilei" forKey:@"name"];
        [student2 setValue:[NSNumber numberWithInt:19] forKey:@"age"];
        NSLog(@"%@",student2);
        
        NSMutableArray *array = [[NSMutableArray alloc] init];
        [array addObject:student1];
        [array addObject:student2];
        
        Grade *grade = [[Grade alloc] init];
        grade.name = @"三年二班";
        grade.students = array;
        NSLog(@"%@",grade);
        
        
        NSArray *studentNames = [grade valueForKeyPath:@"students.name"];
        NSLog(@"%@",studentNames);
        
        NSNumber *sumAge = [grade valueForKeyPath:@"students.@sum.age"];
        NSLog(@"年龄总和:%@",sumAge);
        
        NSNumber *avgAge = [grade valueForKeyPath:@"students.@avg.age"];
        NSLog(@"平均年龄:%@",avgAge);
        
        NSNumber *maxAge = [grade valueForKeyPath:@"students.@max.age"];
        NSLog(@"最大年龄:%@",maxAge);
        
        NSNumber *minAge = [grade valueForKeyPath:@"students.@min.age"];
        NSLog(@"最小年龄:%@",minAge);
    }
    return 0;
}

我们定义了两个学生,然后添加到可变数组,然后赋值给年级的学生属性,我们通过

NSArray *studentNames = [grade valueForKeyPath:@"students.name"];

键路径来一次调用获取所有学生的姓名。

键路径还可以引用一些运算符来进行一些运算,例如求班级学生年龄的总和、平均值、最大值、最小值等等。

运行结果如下:

wKioL1Po8AXAWcoJAAGrxIPTfUs572.jpg

需要注意:KVC需要解析字符串来计算你需要的答案,因此速度比较慢,并且编译器还无法对它进行错误检查。例如想要得出学生的性别

NSArray *studentSexs = [grade valueForKeyPath:@"students.sex"];
NSLog(@"%@",studentSexs);

,但是编译器不能判断它是否是错误的键路径,因此当尝试使用它时,就会出现运行时错误,如下图:

wKiom1Po8s_ic5AXAANMZ83v0YQ917.jpg

KVC的使用大概就这么多吧,睡觉喽~