KVC 原理及自定义实现
一. setValue: forKey: 赋值过程
1.首先寻找setter方法(两个)
- setName:
-setIsName:
2.然后再寻找成员变量
默认 + (BOOL)accessInstanceVariablesDirectly 返回YES;
_key > _isKey > key > isKey
3. 如果以上步骤没有找到key,则会报异常; 也可以重写方法,防止崩溃
-setValue: forUndefinedKey:
二. valueForKey: 取值过程
1.getter方法(三个)
-getKey
-key
-isKey
2.成员变量
_key > _isKey > key > isKey
3.上述没有,可重写,防止崩溃
-valueForUndefinedKey
三. runtime 简单实现 KVC
新建一个NSObject 一个分类
1 #import "NSObject+kvc.h" 2 #import <objc/runtime.h> 3 @implementation NSObject (kvc) 4 - (void)xs_setValue:(id)value forKey:(NSString *)key{ 5 //key 需要合法 6 if (key == nil || key.length == 0) { 7 return; 8 } 9 //一.setter 方法 10 //调用相关setter方法(capitalizedString 首字母大写) 11 NSString *setKey = [NSString stringWithFormat:@"set%@:",[key capitalizedString]]; 12 //调用 13 if ([self respondsToSelector:NSSelectorFromString(setKey)]) { 14 [self performSelector:NSSelectorFromString(setKey) withObject:value]; 15 return; 16 } 17 NSString *setIsKey = [NSString stringWithFormat:@"setIs%@:",[key capitalizedString]]; 18 if ([self respondsToSelector:NSSelectorFromString(setIsKey)]) { 19 [self performSelector:NSSelectorFromString(setIsKey) withObject:value]; 20 return; 21 } 22 23 //异常处理方法 24 if (![self.class accessInstanceVariablesDirectly]) { 25 NSException *exception = [NSException exceptionWithName:@"XSKVC Exception" reason:@"你返回了NO啊!" userInfo:nil]; 26 @throw exception; 27 return; 28 } 29 //二.成员变量 30 unsigned int count = 0; 31 //获取所有成员变量 32 Ivar *ivars = class_copyIvarList([self class], &count);//解释:在C中,copy new create 在堆区开辟内存空间 33 // NSMutableArray *array = [NSMutableArray array]; 34 // for (int i = 0; i<count; i++) { 35 // Ivar ivar = ivars[i]; 36 // const char *name = ivar_getName(ivar); 37 // NSString *keyName = [NSString stringWithUTF8String:name]; 38 // [array addObject:keyName]; 39 // } 40 //_key (按照优先级:_key > _isKey > key > isKey) 41 for (int i = 0; i<count; i++) { 42 Ivar ivar = ivars[i]; 43 NSString *keyName = [NSString stringWithUTF8String:ivar_getName(ivar)]; 44 if ([keyName isEqualToString:[NSString stringWithFormat:@"_%@",key]]) { 45 object_setIvar(self, ivar, value); 46 free(ivars); 47 return; 48 } 49 } 50 //_isKey 51 for (int i = 0; i<count; i++) { 52 Ivar ivar = ivars[i]; 53 NSString *keyName = [NSString stringWithUTF8String:ivar_getName(ivar)]; 54 if ([keyName isEqualToString:[NSString stringWithFormat:@"_is%@",key.capitalizedString]]) { 55 object_setIvar(self, ivar, value); 56 free(ivars); 57 return; 58 } 59 } 60 //key 61 for (int i = 0; i<count; i++) { 62 Ivar ivar = ivars[i]; 63 NSString *keyName = [NSString stringWithUTF8String:ivar_getName(ivar)]; 64 if ([keyName isEqualToString:[NSString stringWithFormat:@"%@",key]]) { 65 object_setIvar(self, ivar, value); 66 free(ivars); 67 return; 68 } 69 } 70 //isKey 71 for (int i = 0; i<count; i++) { 72 Ivar ivar = ivars[i]; 73 NSString *keyName = [NSString stringWithUTF8String:ivar_getName(ivar)]; 74 if ([keyName isEqualToString:[NSString stringWithFormat:@"is%@",key.capitalizedString]]) { 75 object_setIvar(self, ivar, value); 76 free(ivars); 77 return; 78 } 79 } 80 81 //处理异常 82 [self setValue:value forUndefinedKey:key]; 83 free(ivars); 84 85 }