#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 == || 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 = ;
Ivar *ivasList = class_copyIvarList([self class], &count);
// _Key
for (int i = ; 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 = ; 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 = ; 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 = ; 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 == || 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 = ;
Ivar *ivasList = class_copyIvarList([self class], &count);
// _Key
for (int i = ; 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 = ; 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 = ; 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 = ; 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

重写KVC的更多相关文章

  1. KVO VS isa : KVO 建立在 KVC 之上

    Key-Value Observing (KVO) 建立在 KVC 之上,它通过重写 KVC 和监听 setter 方法,向外发送通知. https://blog.csdn.net/y55091811 ...

  2. iOS Runtime原理及使用

    runtime简介 因为Objc是一门动态语言,所以它总是想办法把一些决定工作从编译连接推迟到运行时.也就是说只有编译器是不够的,还需要一个运行时系统 (runtime system) 来执行编译后的 ...

  3. (转)iOS-Runtime知识点整理

    runtime简介 因为Objc是一门动态语言,所以它总是想办法把一些决定工作从编译连接推迟到运行时.也就是说只有编译器是不够的,还需要一个运行时系统 (runtime system) 来执行编译后的 ...

  4. iOS - 回顾总结Runtime原理及使用

    runtime简介 因为Objc是一门动态语言,所以它总是想办法把一些决定工作从编译连接推迟到运行时.也就是说只有编译器是不够的,还需要一个运行时系统 (runtime system) 来执行编译后的 ...

  5. Objective-C之KVC、KVO

    1,KVC(键值编码)  Key Value Coding 1.1在C#中,可以通过字符串反射来获取对象,从而对对象的属性进行读写,Object-C中有同样的实现,通过字符串(属性名词)对对象的属性进 ...

  6. KVC 和 KVO

    KVC 键值编码    全称是Key-value coding,翻译成键值编码.它提供了一种使用字符串而不是访问器方法去访问一个对象实例变量的机制.        1.通过key(成员变量的名称)设置 ...

  7. 11. KVC And KVO

    1. KVC And KVO  的认识 KVC/KVO是观察者模式的一种实现  KVC全称是Key-value coding,翻译成键值编码.顾名思义,在某种程度上跟map的关系匪浅.它提供了一种使用 ...

  8. iOS开发系列--Objective-C之KVC、KVO

    概述 由于ObjC主要基于Smalltalk进行设计,因此它有很多类似于Ruby.Python的动态特性,例如动态类型.动态加载.动态绑定等.今天我们着重介绍ObjC中的键值编码(KVC).键值监听( ...

  9. KVC & KVO

    KVC和KVO看上去又是两个挺牛的单词简写,KVC是Key-Value Coding的简写,是键值编码的意思.KVO是Key-Value  Observing的简写,是键值观察的意思.那么我们能拿KV ...

随机推荐

  1. getter与setter

    var obj = { get a() { return 2; }, get c() { return 34 } } Object.defineProperty( obj, 'b', { get: f ...

  2. 8php字符串的方法

    <?php/** * Created by PhpStorm. * User: DY040 * Date: 2017/9/8 * Time: 16:46 *//*php也有转义字符/*///ec ...

  3. 信息领域热词分析系统--python统计

    统计词语出现的频率,并且按从高到低的顺序报错在文件中 def main(): file=open("F:\大数据\大作业\分词后的文件\data4_xinxi.txt",'r') ...

  4. docker+ bind mount 部署复杂flask应用

    报错如下: [root@test-wenqiang flask-skeleton]# docker run -d -p 80:5000 -v $(pwd):/skeleton --name flask ...

  5. [转]理解js中的原型链,prototype与__proto__的关系

    本文转自:http://rockyuse.iteye.com/blog/1426510 说到prototype,就不得不先说下new的过程. 我们先看看这样一段代码: 1 <script typ ...

  6. (转)Rsync 排错案例解析

    Rsync 排错案例解析 原文:http://blog.51cto.com/irow10/1827306 错误一. 执行计划任务的备份脚本后没有看到备份的文件 1.首先查看crontab日志是否执行文 ...

  7. (转)Python作业day2购物车

    Python作业day2购物车 原文:https://www.cnblogs.com/spykids/p/5163108.html 流程图: 实现情况: 可自主注册, 登陆系统可购物,充值(暂未实现) ...

  8. [PHP]生成随机数(建立字典)

    代码如下 : //建立有76个字符组成的字典 $pattern='1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM!@#$% ...

  9. pta08-图7 公路村村通 (30分)

    08-图7 公路村村通   (30分) 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本. 输入格式: 输入数据包括城镇数目正整数N ...

  10. Vue ajax跨域请求

    Vue webpack-dev-server实现跨域请求 思路 配置webpack-dev-server,代理某一个路径到目标路径,同是更改源和重写 Vue里定义一个全部变量:site Vue.pro ...