#import "NSObject+WQKVC.h" #import <objc/runtime.h> /** KVC 首先调用的方法顺序: |- setter: setKey -> setIsKey |- getter: getKey -> key -> isKey |- - (Bool)accessInstanceVariablesDirectly 不为NO ,默认为YES 查找成员变量的顺序: |- _key -> _isKey -> key -> isKey **/ @implementation NSObject (WQKVC) - (void)WQ_setValue:(id)value forKey:(NSString *)key { //判断key的合法性 if (key.length == 0 || key == nil) { return; } NSString *setKey = [NSString stringWithFormat:@"set%@",key.capitalizedString]; SEL setKeyMethod = NSSelectorFromString(setKey); if ([self respondsToSelector:setKeyMethod]) { [self performSelector:setKeyMethod withObject:value]; return; } NSString *setIsKey = [NSString stringWithFormat:@"setIs%@",key.capitalizedString]; SEL setIsKeyMethod = NSSelectorFromString(setIsKey); if ([self respondsToSelector:setIsKeyMethod]) { [self performSelector:setIsKeyMethod withObject:value]; return; } if (![self.class accessInstanceVariablesDirectly]) { NSException *exception = [NSException exceptionWithName:@"WQKVC Exception" reason:@"不能设置为NO!" userInfo:nil]; @throw exception; return; } unsigned int count = 0; Ivar *ivasList = class_copyIvarList([self class], &count); // _Key for (int i = 0; i < count ; i ++) { NSString *keyStr = [NSString stringWithUTF8String:ivar_getName(ivasList[i])]; if ([keyStr isEqualToString:[NSString stringWithFormat:@"_%@",key.capitalizedString]]) { object_setIvar(self, ivasList[i], value); free(ivasList); return; } } // _isKey for (int i = 0; i < count ; i ++) { NSString *keyStr = [NSString stringWithUTF8String:ivar_getName(ivasList[i])]; if ([keyStr isEqualToString:[NSString stringWithFormat:@"_is%@",key.capitalizedString]]) { object_setIvar(self, ivasList[i], value); free(ivasList); return; } } // Key for (int i = 0; i < count ; i ++) { NSString *keyStr = [NSString stringWithUTF8String:ivar_getName(ivasList[i])]; if ([keyStr isEqualToString:key]) { object_setIvar(self, ivasList[i], value); free(ivasList); return; } } // isKey for (int i = 0; i < count ; i ++) { NSString *keyStr = [NSString stringWithUTF8String:ivar_getName(ivasList[i])]; if ([keyStr isEqualToString:[NSString stringWithFormat:@"is%@",key.capitalizedString]]) { object_setIvar(self, ivasList[i], value); free(ivasList); return; } } // 异常处理! [self setValue:value forUndefinedKey:key]; free(ivasList); } - (id)WQ_valueForKey:(NSString *)key { if (key.length == 0 || key == nil) { return nil; } // getKey -- Method NSString *getKey = [NSString stringWithFormat:@"get%@",key.capitalizedString]; SEL getKeyMethod = NSSelectorFromString(getKey); if ([self respondsToSelector:getKeyMethod]) { return [self performSelector:getKeyMethod withObject:nil]; } // key -- Method SEL KeyMethod = NSSelectorFromString(key); if ([self respondsToSelector:getKeyMethod]) { return [self performSelector:KeyMethod withObject:nil]; } // isKey -- Method NSString *isKey = [NSString stringWithFormat:@"is%@",key.capitalizedString]; SEL isKeyMethod = NSSelectorFromString(isKey); if ([self respondsToSelector:isKeyMethod]) { return [self performSelector:isKeyMethod withObject:nil]; } if (![self.class accessInstanceVariablesDirectly]) { NSException *exception = [NSException exceptionWithName:@"WQKVC Exception" reason:@"不能设置为NO!" userInfo:nil]; @throw exception; return nil; } unsigned int count = 0; Ivar *ivasList = class_copyIvarList([self class], &count); // _Key for (int i = 0; i < count ; i ++) { NSString *keyStr = [NSString stringWithUTF8String:ivar_getName(ivasList[i])]; if ([keyStr isEqualToString:[NSString stringWithFormat:@"_%@",key.capitalizedString]]) { Ivar ivar_temp = ivasList[i]; free(ivasList); return object_getIvar(self, ivar_temp); } } // _isKey for (int i = 0; i < count ; i ++) { NSString *keyStr = [NSString stringWithUTF8String:ivar_getName(ivasList[i])]; if ([keyStr isEqualToString:[NSString stringWithFormat:@"_is%@",key.capitalizedString]]) { Ivar ivar_temp = ivasList[i]; free(ivasList); return object_getIvar(self, ivar_temp); } } // Key for (int i = 0; i < count ; i ++) { NSString *keyStr = [NSString stringWithUTF8String:ivar_getName(ivasList[i])]; if ([keyStr isEqualToString:key]) { Ivar ivar_temp = ivasList[i]; free(ivasList); return object_getIvar(self, ivar_temp); } } // isKey for (int i = 0; i < count ; i ++) { NSString *keyStr = [NSString stringWithUTF8String:ivar_getName(ivasList[i])]; if ([keyStr isEqualToString:[NSString stringWithFormat:@"is%@",key.capitalizedString]]) { Ivar ivar_temp = ivasList[i]; free(ivasList); return object_getIvar(self, ivar_temp); } } free(ivasList); return [self valueForUndefinedKey:key]; } @end