KCV的基本使用
// 设值
- (void)setValue:(id)value forKey:(NSString *)key;
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
// 取值
- (id)valueForKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
// Student类
@interface Student : NSObject
@property (nonatomic, copy) NSString *name;
@end
// Person类
@interface Person : NSObject
@property (nonatomic, assign) int age;
@property (nonatomic, strong) Student *student;
@end
// 具体使用
Person *person = [[Person alloc] init];
person.student = [[Student alloc] init];
[person setValue:@(10) forKey:@"age"];
[person setValue:@"Sunny" forKeyPath:@"student.name"];
NSLog(@"age:%@ name:%@", [person valueForKey:@"age"], [person valueForKeyPath:@"student.name"]);
KVC的设值原理
// Person类
@interface Person : NSObject {
@public
int _age;
int _isAge;
int age;
int isAge;
}
@end
@implementation Person
+ (BOOL)accessInstanceVariablesDirectly {
return NO;
}
- (void)setAge:(int)age {
NSLog(@"%s",__func__);
}
- (void)_setAge:(int)age {
NSLog(@"%s",__func__);
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
NSLog(@"%s",__func__);
}
@end
// ViewController类
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Person *person = [[Person alloc] init];
[person setValue:@(10) forKey:@"age"];
}
@end
解释:
1、当存在setKey
方法时,调用setKey
。
2、当setKey
方法不存在,存在_setKey
方法时,调用_setKey
。
3、当setKey
和_setKey
都不存在时,检查+(BOOL)accessInstanceVariablesDirectly
返回值。
4、如果+(BOOL)accessInstanceVariablesDirectly
返回NO,调用-(void)setValue:(id)value forUndefinedKey:(NSString *)key
,程序结束。
5、如果+(BOOL)accessInstanceVariablesDirectly
返回YES,按照_key
、_isKey
、key
、isKey
的顺序查找成员变量赋值。
6、如果按照上面的流程都没找到,调用-(void)setValue:(id)value forUndefinedKey:(NSString *)key
,程序结束。
用一张图来总结KVC设值的查找顺序:
总结:
按照上面流程都没有查找到对应的方法或成员变量可以赋值就是调用我们常见的一个方法:
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
抛出异常。
注意:
针对KVC赋值,即使没有找到setKey
或_setKey
,只要找到一个成员变量也是会触发KVO的,KVC本身自己在内部会去通知相应的observer观察者某个属性发生了变化。
其实就是在内部调用了:
- (void)willChangeValueForKey:(NSString *)key;
- (void)didChangeValueForKey:(NSString *)key;
KVC的取值原理
// Person类
@interface Person : NSObject {
@public
int _age;
int _isAge;
int age;
int isAge;
}
@end
@implementation Person
+ (BOOL)accessInstanceVariablesDirectly {
return NO;
}
- (void)getAge {
NSLog(@"%s",__func__);
}
- (void)age {
NSLog(@"%s",__func__);
}
- (void)isAge {
NSLog(@"%s",__func__);
}
- (void)_age {
NSLog(@"%s",__func__);
}
- (id)valueForUndefinedKey:(NSString *)key {
NSLog(@"%s",__func__);
}
@end
// ViewController 类
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Person *person = [[Person alloc] init];
[person valueForKey:@"age"];
}
@end
解释:
1、当存在getKey
方法时,调用getKey
。
2、当getKey
方法不存在,存在key
方法时,调用key
。
3、当getKey
、key
方法不存在,存在isKey
方法时,调用isKey
。
4、当getKey
、key
、isKey
方法不存在,存在_key
方法时,调用_key
。
5、当getKey
、key
、isKey
、_key
都不存在时,检查+(BOOL)accessInstanceVariablesDirectly
返回值。
6、如果+(BOOL)accessInstanceVariablesDirectly
返回NO,调用- (id)valueForUndefinedKey:(NSString *)key
,程序结束。
7、如果+(BOOL)accessInstanceVariablesDirectly
返回YES,按照_key
、_isKey
、key
、isKey
的顺序查找成员变量赋值。
8、如果按照上面的流程都没找到对应的方法或成员变量,调用- (id)valueForUndefinedKey:(NSString *)key
,程序结束。
用一张图来总结KVC取值的查找顺序:
总结:
按照上面流程都没有查找到对应的方法或成员变量可以赋值就是调用我们常见的一个方法:
- (id)valueForUndefinedKey:(NSString *)key
抛出异常。
写在最后
关于iOS里面的KVC设值、取值的相关顺序就写到这里了,如有错误请指教,欢迎去我的个人博客逛逛。
网友评论