除了一般的赋值和取值的方法,我们还可以用Key-Value-Coding(KVC)键值编码来访问你要存取的类的属性。
如何使用KVC存取对象属性呢?看个示例
一、使用KVC存数据
定义一个person类
.h文件
#import <Foundation/Foundation.h> @class Dog; @interface Person : NSObject /** 姓名*/ @property (nonatomic, copy)NSString *name; /** 钱*/ @property (nonatomic, assign)double money; /** 宠物*/ @property (nonatomic, strong)Dog *dog; @end
.m文件
#import "Person.h" @implementation Person { @private int _age; } - (void)say { NSLog(@"age = %i", _age); } @end
再定义一个dog类
.h
#import <Foundation/Foundation.h> @interface Dog : NSObject /** 狗的外号*/ @property (nonatomic, copy)NSString *name; /** 狗的价格*/ @property (nonatomic, assign)double price; @end
.m
#import "Dog.h" @implementation Dog @end
先创建一个对象
Person *p = [[Person alloc] init];
p.name = @"chg"; // setter
p.money = 998.0;
除了这种方式赋值,可以使用KVC
#pragma mark 单个值 // KVC == KEY VALUE CODING // Value : 值, 只能传对象 // forKey: 需要给谁(哪个属性)赋值 // setValue:forKey:方法, 只能给对象的直接属性赋值 [p setValue:@"lmj" forKey:@"name"]; // @(998.0) == [NSNumber numberWithDouble:(double)] [p setValue:@(668.0) forKey:@"money"];
#pragma mark 多层赋值 p.dog = [Dog new]; p.dog.name == [[p dog] setName:] p.dog.name = @"wangwang"; p.dog.price = 110.0; // setValue:forKeyPath: 可以给对象的间接属性赋值. 多层赋值 // 建议: 以后在开发中都使用setValue:forKeyPath: [p setValue:@"xiaoqiang" forKeyPath:@"dog.name"]; [p setValue:@(110) forKeyPath:@"dog.price"];
#pragma mark 给私有成员变量赋值 [p setValue:@"lnj" forKey:@"_name"]; [p setValue:@(30) forKey:@"_age"]; SEL sel = @selector(say); [p performSelector:sel]; [p say];
#pragma mark 字典转模型 NSDictionary *dict = @{ @"name":@"xxx", @"money": @(998.1), // @"score":@(100) @"dog":@{ @"name":@"wangcai", @"price":@(110) } }; // 注意点: // 1.如果想使用KVC进行字典转模型, 那么字典中的key必须和模型中的属性一模一样(个数 + 名称) // this class is not key value coding-compliant for the key score.' // 2.如果使用KVC进行字典转模型, 只能对当前调用KVC方法的对象进行转换, 不能对它的属性的对象进行转换 // setValuesForKeysWithDictionary:方法内部的实现原理 // 1.会拿到字典中的key, 然后根据这个key取出字典中的值, 然后再根据这个key赋值给对象 // [p setValue:@"xxx" forKey:@"name"]; [p setValuesForKeysWithDictionary:dict]; NSLog(@"p.dog = %@", p.dog); NSLog(@"name = %@, money = %f", p.name, p.money); // getter
二、使用KVC取数据
首先设置一些数据
Person *p = [Person new]; p.name = @"chg"; p.money = 998; p.dog = [Dog new]; p.dog.name = @"wangcai"; p.dog.price = 110;
有以下几种方式取值
#pragma mark 获取单个值 NSString *name = [p valueForKey:@"name"]; NSLog(@"name = %@", name); double money = [[p valueForKey:@"money"] doubleValue]; NSLog(@"money = %f", money);
#pragma mark 获取多层值 NSString *dogName = [p valueForKey:@"dog.name"]; NSString *dogName = [p valueForKeyPath:@"dog.name"]; NSLog(@"dogName = %@", dogName);
#pragma mark 模型转字典 NSDictionary *dict = [p dictionaryWithValuesForKeys:@[@"name", @"money"]];
#pragma mark 获取数组中对象的值 Person *p1 = [Person new]; p1.name = @"zs"; p1.money = 111; Person *p2 = [Person new]; p2.name = @"ls"; p2.money = 222; Person *p3 = [Person new]; p3.name = @"ww"; p3.money = 666; NSArray *arr = @[p1, p2, p3]; // 如果数组中的元素都是同一种类型的数据, 可以使用KVC获取数组中所有对象的某个属性的值 NSArray *res = [arr valueForKeyPath:@"name"]; NSLog(@"res = %@", res);
#pragma mark 运算符 // 获取arr数组中money的平均值 id res1 = [arr valueForKeyPath:@"@avg.money"]; // 获取arr数组中money的最大值 id res2 = [arr valueForKeyPath:@"@max.money"]; // 获取arr数组中money的最小值 id res3 = [arr valueForKeyPath:@"@max.money"]; NSLog(@"res1 = %@,res2 = %@,res3 = %@", res1,res2,res3);