重写KVC
#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的更多相关文章
- KVO VS isa : KVO 建立在 KVC 之上
Key-Value Observing (KVO) 建立在 KVC 之上,它通过重写 KVC 和监听 setter 方法,向外发送通知. https://blog.csdn.net/y55091811 ...
- iOS Runtime原理及使用
runtime简介 因为Objc是一门动态语言,所以它总是想办法把一些决定工作从编译连接推迟到运行时.也就是说只有编译器是不够的,还需要一个运行时系统 (runtime system) 来执行编译后的 ...
- (转)iOS-Runtime知识点整理
runtime简介 因为Objc是一门动态语言,所以它总是想办法把一些决定工作从编译连接推迟到运行时.也就是说只有编译器是不够的,还需要一个运行时系统 (runtime system) 来执行编译后的 ...
- iOS - 回顾总结Runtime原理及使用
runtime简介 因为Objc是一门动态语言,所以它总是想办法把一些决定工作从编译连接推迟到运行时.也就是说只有编译器是不够的,还需要一个运行时系统 (runtime system) 来执行编译后的 ...
- Objective-C之KVC、KVO
1,KVC(键值编码) Key Value Coding 1.1在C#中,可以通过字符串反射来获取对象,从而对对象的属性进行读写,Object-C中有同样的实现,通过字符串(属性名词)对对象的属性进 ...
- KVC 和 KVO
KVC 键值编码 全称是Key-value coding,翻译成键值编码.它提供了一种使用字符串而不是访问器方法去访问一个对象实例变量的机制. 1.通过key(成员变量的名称)设置 ...
- 11. KVC And KVO
1. KVC And KVO 的认识 KVC/KVO是观察者模式的一种实现 KVC全称是Key-value coding,翻译成键值编码.顾名思义,在某种程度上跟map的关系匪浅.它提供了一种使用 ...
- iOS开发系列--Objective-C之KVC、KVO
概述 由于ObjC主要基于Smalltalk进行设计,因此它有很多类似于Ruby.Python的动态特性,例如动态类型.动态加载.动态绑定等.今天我们着重介绍ObjC中的键值编码(KVC).键值监听( ...
- KVC & KVO
KVC和KVO看上去又是两个挺牛的单词简写,KVC是Key-Value Coding的简写,是键值编码的意思.KVO是Key-Value Observing的简写,是键值观察的意思.那么我们能拿KV ...
随机推荐
- mysql 存储过程(代码块)
大纲: 创建.删除.调用. 声明变量.变量赋值 声明游标 声明异常处理器 判断 循环 使用心得 一.创建.删除.调用 创建 DELIMITER $$ #修改分隔符 )) #括号里是入参.IN代表传入的 ...
- python3与python2的区别 记录一波
1.性能 Py3.0运行 pystone benchmark的速度比Py2.5慢30%.Guido认为Py3.0有极大的优化空间,在字符串和整形操作上可 以取得很好的优化结果. Py3.1性能比Py2 ...
- 使用cucumber & selenium实现一个简单的bddtest
1.Cucumber介绍 + feature : read requirement +scenario : testing situation,including + Given/ + when/ + ...
- CSAPP阅读笔记-链接-第七章-P464-P500
链接概述 经预处理器->编译器->汇编器处理后,源文件可被转化为一组可重定位目标文件,链接器将它们组合起来形成可执行文件. 每个可重定位目标文件由不同的“代码节”和“数据节”组成,每一个节 ...
- BigDecimal的使用举例,包括阶乘的相加求法思路
对于高精度要求或者运算数较大的的计算,应该使用bigdecimal类实现 import java.math.BigDecimal; public class TestSysin { public st ...
- contiki源码阅读之mmem.c
上次我们说了list,这次我们就借着mmem.c的代码来用一下这个链表. 代码目录是./core/lib/mmem.c 结构体定义如下 struct mmem { struct mmem *next; ...
- RadControl使用相同的Theme
我們僅須對兩個地方加一些程式碼,就可使所有的RadControl擁用相的Theme,如此一下不但可使Ap內布景主題一致,設計者亦不需要對每個控件做字型,顏色,大小等等瑣碎的設計. App.Xaml.c ...
- 通过进入单用户模式解决linux中的rc.local修改后无法启动的问题
问题:本想将teamviewer这个软件随linux自启动,所以将其启动命令放在rc.local中,但是重启后发现linux启动不起来了,系统前面都是正常启动的,就是无法进入帐户登陆界面,无法输入ro ...
- ASP.NET WebForm 之 Ajax 请求后端处理
概述 ASP.NET MVC中的异步用途非常广泛,操作起来也非常简单.前台请求异步请求 Controller下的Action 方法,后端返回ActionResult 即可.但是在ASP.NET Web ...
- jq获取页面距离
$(window).height() //获取的是当前可视窗口的高度,也就是用户能看到的窗口的高度,是不变的(在窗口大小不变的前提下) $(document).height() //获取的是窗口内文档 ...