KVC相关
一、 iOS成员变量,实例变量,属性变量的区别
@interface Person : NSObject
{
@public
NSString *name;
id object; // id是一种特殊的Class,是OC特有的OC对象
UIButton *btn;// 实例变量--由Class进行实例化而生成的对象为实例变量
int age;
}// 大括号内均为成员变量
// 实例变量是一种特殊的成员变量
// 属性 有默认的 setter 和 getter 方法
// 当 LLVM 发现一个属性 没有匹配的 成员变量 时,会生成getter&setter方法并创建一个下划线的成员变量
// property自动生成的setter和getter方法都会自动生成_<key>的变量,如果只重写setter或getter中的一个,另一个还是会生成下划线变量,但是同时重写setter和getter的话就无法自动生成下划线变量了
@property (nonatomic, copy) NSString *name2;
@property (nonatomic, strong) Son *son;
- (void)walk;
+ (void)study;
@end
二、KVC取值、赋值原理
*学习方式:
1、分析源码 - 没有开源
2、官方文档:Key-Value Coding Programming Guide
KVC是什么
Key-Value是一种通过NSKeyValueCoding协议间接访问成员变量的机制
KVC有什么作用
键值编码
- (void)viewDidLoad
{
[super viewDidLoad];
Person *p = [Person new];
Son *s = [Son new];
[p setValue:s forKeyPath:@"son"];
[p setValue:@"hehe" forkey:@"name2"];
[p setValue:@"didi" forKeyPath:@"son.subject_Son"];
}
KVC的原理是什么
赋值过程 setValue:forKey
1、先查找set<key>,_set<Key>
方法,若存在则不走“2、”
2、若没有上述方法且accessInstanceVariablesDirectly==YES,则先存在_<Key>,_is<Key>,<Key>,is<Key>
中
*上述情况均只执行一次
.h
@interface Person : NSObject{
@public
NSString *name;
NSString *_name;
NSString *_isName;
NSString *isName;
}
.m
//此时Person类中没有set<key>,_set<Key>方法
Person *p = [[Person alloc] init];
[p setValue:@"hehe" forKey:@"name"];
NSLog(@"p->isName:%@",p->isName);
NSLog(@"p->name:%@ - p->isName:%@",p->name,p->isName);
NSLog(@"p->name:%@ - p->isName:%@ - p->_isName:%@",p->name,p->isName,p->_isName);
NSLog(@"p->name:%@ - p->isName:%@ - p->_name:%@ - p->_isName:%@",
p->name,p->isName,p->_name,p->_isName);
输出:
p->isName:(null)
p->name:(null) - p->isName:(null)
p->name:(null) - p->isName:(null) - p->_isName:(null)
p->name:(null) - p->isName:(null) - p->_name:hehe - p->_isName:(null)
取值过程 valueForKey:
1、普通类型
//如果重写了这些方法,则会调用重写的方法,按从上到下的顺序,只调一次
- (NSString *)getName
{
NSLog(@"%s",__func__);
return NSStringFromSelector(_cmd);
}
- (NSString *)name
{
NSLog(@"%s",__func__);
return NSStringFromSelector(_cmd);
}
- (NSString *)isName
{
NSLog(@"%s",__func__);
return NSStringFromSelector(_cmd);
}
- (NSString *)_name
{
NSLog(@"%s",__func__);
return NSStringFromSelector(_cmd);
}
2、集合类型:array、set
3、如没有一系列的getter方法,需将accessInstanceVariablesDirectly(是否开启间接访问) 设为为 YES(默认值也是YES)时,访问顺序为:
_<key>,_is<key>,<key>,is<key>
.h
@interface Person : NSObject{
@public
NSString *name;
//NSString *_name;
NSString *_isName;
NSString *isName;
}
.m
Person *p = [[Person alloc] init];
[p setValue:@"hehe" forKey:@"name"];
//p->_name = @"_name";
p->_isName = @"_isName"; // MAP -- KEY - VALUE
p->name = @"name";
p->isName = @"isName";
NSLog(@"%@",[p valueForKey:@"name"]); // 方法 getName
输出:
//_name
_isName
*解释:
在赋值时,若set<key>,_set<Key>
不存在,但name,_name,_isName,isName
都存在,则 [p setValue:@"hehe" forKey:@"name"]
实际上是将hehe
赋值在_name
中,并且不存在其他属性中,若_name
不存在则赋值在_isName
中。
所以取值时,存的时候存在哪就在哪取,不然取不到。
网友评论