KVC基本的使用
- setValue:forKey:,setValue:forKeyPath:
Student *aStudent = [[Student alloc] init];
[aStudent setValue:@"123" forKey:@"ivar"];
[aStudent setValue:[[Test alloc] init] forKey:@"test"];
[aStudent setValue:@"test123" forKeyPath:@"test.name"];
NSLog(@"aStudent = %@",aStudent);
setValue:forKey:只支持一级属性
setValue:forKeyPath: 支持多级属性,也支持一级属性
2. valueForKey:,valueForKeyPath:
NSString *ivar = [aStudent valueForKey:@"ivar"];
NSString *name = [aStudent valueForKeyPath:@"test.name"];
valueForKey:只支持一级属性
valueForKeyPath: 支持多级属性,也支持一级属性
- KVC可以获取.h文件.m文件的属性(runtime也一样)
KVC底层原理
- 先调用key对应的set方法
#import "Student.h"
@implementation Student
- (void)setName:(NSString *)name{
_name = @"test";
}
@end
Student *aStudent = [[Student alloc] init];
[aStudent setValue:@"000" forKey:@"name"];
NSLog(@"name = %@",aStudent.name);
如上方法验证,首先重写了name的setter方法,并打一个断点。之后利用kvc给name属性赋值。程序运行后发现走了断点,并打印了name属性的值是test。说明了kvc首先调用了属性的setter方法。
2. 如果setter方法没有将会查找属性,直接属性赋值
#import "Student.h"
@implementation Student
@dynamic name;
@end
- (void)viewDidLoad {
[super viewDidLoad];
Student *aStudent = [[Student alloc] init];
[aStudent setValue:@"000" forKey:@"name"];
NSLog(@"name = %@",aStudent.name);
}
如上方法验证,首先将name属性声明为@dynamic。即不自动课程setter方法。之后进行kvc赋值。发现崩溃。说明了kvc在找不到setter方法后将直接对属性赋值,这时候最终调用的是setter方法,应为找不到setter方法,所以崩溃。
3. 如果找不到属性将会找成员变量,直接对成员变量赋值
@interface Student : NSObject <YYModel>
{
NSString *ivar;
}
- (void)viewDidLoad {
[super viewDidLoad];
Student *aStudent = [[Student alloc] init];
[aStudent setValue:@"000" forKey:@"ivar"];
NSLog(@"aStudent = %@",aStudent);
}
如上方法验证,首先定义一个ivar成员变量。之后进行kvc对ivar赋值。然后打印aStudent对象,在这里设置一个断点会发现aStudent对象内部的ivar成员变量被成功赋值了000字串。说明了,kvc在找不到属性后会找相应的成员变量。