1. KVC
- KVC的全称是
Key-Value Coding
,俗称“键值编码”,可以通过一个key来访问某个属性。 - 常见的API有:
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;//通过keyPath可以设置属性的属性
- (void)setValue:(id)value forKey:(NSString *)key;//通过key设置自己的属性
- (id)valueForKeyPath:(NSString *)keyPath;//通过keyPath访问属性的属性
- (id)valueForKey:(NSString *)key; //通过key访问自己的属性
-
kvc设置属性原理:
-
setValue:forKey
的原理详解:- 先去寻找
setKey:
方法(即对应key的set方法),找到了就去传递参数调用方法; - 如果没找到,再去寻找
_setKey:
的方法,找到可传值; - 没找到就去查看
+ (BOOL)accessInstanceVariablesDirectly;
这个方法是不是设置为YES(默认是YES),如果设置的是YES这表示直可以接访问实例成员变量; - 然后会去查看有没有
_key
的成员变量、有就设值; - 没有就去查看有没有
_isKey
的成员变量、有就设值; - 没有就去查看有没有
key
的成员变量、有就设值; - 没有就去查看有没有
isKey
的成员变量、有就设值; - 如果还没找到就会抛异常:
NSUnknownKeyException
- 如果上面
accessInstanceVariablesDirectly
设置为NO,并且setKey:、_setKey:
这两个set方法没找到就会抛异常,不会去访问属性。
示例1:
- 先去寻找
@interface Person : NSObject{
@public
// int _age;
int _isAge;
int age;
int isAge;
}
/**age属性*/
//@property(nonatomic,assign) int age;
@end
@implementation Person
//-(void)setAge:(int)age{
// _age = age;
//}
//-(void)_setAge:(int)age{
// _age = age;
//}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person * p = [[Person alloc]init];
[p setValue:@18 forKey:@"age"];
// NSLog(@"%d",p->age);
}
return 0;
}
上面代码和调试结果可以看出:当把两个set方法和_age
成员变量注销后会优先访问_isAge
成员变量,可以通过注销其他的成员变量一次证明方法的顺序,这里不再赘述。
在Person类中重写+ (BOOL)accessInstanceVariablesDirectly;
方法,并设置返回值为NO
,编译就会抛异常。
@implementation Person
+ (BOOL)accessInstanceVariablesDirectly{
return NO;
}
@end
-
kvc取值原理:
- valueForKey:原理详解:
- 同设置属性一样,取值时访问方法的顺序是
getKey
、key
、isKey
、_key
,找到前面的方法就调用给成员变量取值就不会再往下找了。 - 如果上面的方法都没找到就会去查看accessInstanceVariablesDirectly`这个方法是不是设置为YES,如果设置的是YES这表示直可以接访问实例成员变量;
- 设置成员变量的顺序为:
_key
、_isKey
、key
、iskey
找到前面的成员变量取值就不会再往下找了; - 如果没有找到上面的成员变量,就会抛异常:
NSUnknownKeyException
- 如果上面
accessInstanceVariablesDirectly
设置为NO,并且上面的方法都没有找到也会抛异常。
-
注意
:上面的赋值取值方法以及成员变量可以是私有的,依然可以访问,即KVC是可以访问对象的私有属性的。
//.m文件
#import "Person.h"
@interface Person(){
@private
int _age;
int _isAge;
int age;
int isAge;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person * p = [[Person alloc]init];
[p setValue:@18 forKey:@"age"];
NSLog(@"%@",[p valueForKey:@"age"]);
}
return 0;
}