iOS开发——UI基础-KVC

时间:2022-02-23 21:03:03

除了一般的赋值和取值的方法,我们还可以用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:@() forKeyPath:@"dog.price"];
#pragma mark 给私有成员变量赋值
[p setValue:@"lnj" forKey:@"_name"];
[p setValue:@() 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":@()
}
}; // 注意点:
// 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 = ;
p.dog = [Dog new];
p.dog.name = @"wangcai";
p.dog.price = ;

有以下几种方式取值

#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 = ; Person *p2 = [Person new];
p2.name = @"ls";
p2.money = ; Person *p3 = [Person new];
p3.name = @"ww";
p3.money = ; 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);