KVC是怎么使用的,我相信绝大多数的开发者都很清楚,我在这里就不再写简单的使用KVC来设值和取值的代码了,首�先我们来探讨KVC在内部是按什么样的顺序来寻找key的。
设值
当调用setValue:属性值 forKey:@”name“的代码时,底层的执行机制如下:
• 程序优先调用set
• 如果没有找到setName:方法,KVC机制会检查+ (BOOL)accessInstanceVariablesDirectly方法有没有返回YES,默认该方法会返回YES,如果你重写了该方法让其返回NO的话,那么在这一步KVC会执行setValue:forUndefinedKey:方法,不过一般开发者不会这么做。所以KVC机制会搜索该类里面有没有名为
• 如果该类即没有set
• 和上面一样,如果该类即没有set
• 如果上面列出的方法或者成员变量都不存在,系统将会执行该对象的setValue:forUndefinedKey:方法,默认是抛出异常。
如果开发者想让这个类禁用KVC里,那么重写+ (BOOL)accessInstanceVariablesDirectly方法让其返回NO即可,这样的话如果KVC没有找到set
下面我们来让代码来测试一下上面的KVC机制
@interface Dog : NSObject@end@implementation Dog
{
NSString* toSetName;
NSString* isName;
//NSString* name;
NSString* _name;
NSString* _isName;
}// -(void)setName:(NSString*)name{// toSetName = name;// }//-(NSString*)getName{// return toSetName;//}
+(BOOL)accessInstanceVariablesDirectly{
return NO;
}
-(id)valueForUndefinedKey:(NSString *)key{
NSLog(@"出现异常,该key不存在%@",key);
return nil;
}
-(void)setValue:(id)value forUndefinedKey:(NSString *)key{
NSLog(@"出现异常,该key不存在%@",key);
}@endint main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
Dog* dog = [Dog new];
[dog setValue:@"newName" forKey:@"name"];
NSString* name = [dog valueForKey:@"toSetName"];
NSLog(@"%@",name);
}
return 0;
}
首先我们先重写accessInstanceVariablesDirectly方法让其返回NO,再运行代码(注意上面注释的部分),Xcode直接打印出
2016-04-15 15:52:12.039 DemoKVC[9681:287627] 出现异常,该key不存在name
2016-04-15 15:52:12.040 DemoKVC[9681:287627] 出现异常,该key不存在toSetName
2016-04-15 15:52:12.040 DemoKVC[9681:287627] (null)
这说明了重写+(BOOL)accessInstanceVariablesDirectly方法让其返回NO后,KVC找不到setName:方法后,不再去找name系列成员变量,而是直接调用setValue:forUndefinedKey:方法
所以开发者如果不想让自己的类实现KVC,就可以这么做。
下面那两个setter和getter的注释取消掉,再把
NSString* name = [dog valueForKey:@"toSetName"]; 换成 NSString* name = [dog valueForKey:@"name"];
XCode就可以正确地打印出正确的值了
2016-04-15 15:56:22.130 DemoKVC[9726:289258] newName
下面再注释掉accessInstanceVariablesDirectly方法,就能测试其他的key查找顺序了,为了节省篇幅,剩下的的KVC对于key寻找机制就不在这里展示了,有兴趣的读者可以写代码去验证。
本文作者:张元一
<上一篇 | 目录 | 下一篇> |
---|