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 一个分类
#import "NSObject+kvc.h"
#import <objc/runtime.h>
@implementation NSObject (kvc)
- (void)xs_setValue:(id)value forKey:(NSString *)key{
//key 需要合法
if (key == nil || key.length == ) {
return;
}
//一.setter 方法
//调用相关setter方法(capitalizedString 首字母大写)
NSString *setKey = [NSString stringWithFormat:@"set%@:",[key capitalizedString]];
//调用
if ([self respondsToSelector:NSSelectorFromString(setKey)]) {
[self performSelector:NSSelectorFromString(setKey) withObject:value];
return;
}
NSString *setIsKey = [NSString stringWithFormat:@"setIs%@:",[key capitalizedString]];
if ([self respondsToSelector:NSSelectorFromString(setIsKey)]) {
[self performSelector:NSSelectorFromString(setIsKey) withObject:value];
return;
} //异常处理方法
if (![self.class accessInstanceVariablesDirectly]) {
NSException *exception = [NSException exceptionWithName:@"XSKVC Exception" reason:@"你返回了NO啊!" userInfo:nil];
@throw exception;
return;
}
//二.成员变量
unsigned int count = ;
//获取所有成员变量
Ivar *ivars = class_copyIvarList([self class], &count);//解释:在C中,copy new create 在堆区开辟内存空间
// NSMutableArray *array = [NSMutableArray array];
// for (int i = 0; i<count; i++) {
// Ivar ivar = ivars[i];
// const char *name = ivar_getName(ivar);
// NSString *keyName = [NSString stringWithUTF8String:name];
// [array addObject:keyName];
// }
//_key (按照优先级:_key > _isKey > key > isKey)
for (int i = ; i<count; i++) {
Ivar ivar = ivars[i];
NSString *keyName = [NSString stringWithUTF8String:ivar_getName(ivar)];
if ([keyName isEqualToString:[NSString stringWithFormat:@"_%@",key]]) {
object_setIvar(self, ivar, value);
free(ivars);
return;
}
}
//_isKey
for (int i = ; i<count; i++) {
Ivar ivar = ivars[i];
NSString *keyName = [NSString stringWithUTF8String:ivar_getName(ivar)];
if ([keyName isEqualToString:[NSString stringWithFormat:@"_is%@",key.capitalizedString]]) {
object_setIvar(self, ivar, value);
free(ivars);
return;
}
}
//key
for (int i = ; i<count; i++) {
Ivar ivar = ivars[i];
NSString *keyName = [NSString stringWithUTF8String:ivar_getName(ivar)];
if ([keyName isEqualToString:[NSString stringWithFormat:@"%@",key]]) {
object_setIvar(self, ivar, value);
free(ivars);
return;
}
}
//isKey
for (int i = ; i<count; i++) {
Ivar ivar = ivars[i];
NSString *keyName = [NSString stringWithUTF8String:ivar_getName(ivar)];
if ([keyName isEqualToString:[NSString stringWithFormat:@"is%@",key.capitalizedString]]) {
object_setIvar(self, ivar, value);
free(ivars);
return;
}
} //处理异常
[self setValue:value forUndefinedKey:key];
free(ivars); }
KVC 原理及自定义实现的更多相关文章
- 【原】iOS学习之KVC原理
1. KVC的实现原理 遍历字典里面所有的key,以name为例 去模型中查找有没有setName:方法,有就直接调用赋值 假如没有找到setName:方法,就会继续查找有没有_name属性,有就_n ...
- JAVA之旅(二十五)——文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine
JAVA之旅(二十五)--文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine 我们继续IO上个篇 ...
- Spring MVC内容协商实现原理及自定义配置【享学Spring MVC】
每篇一句 在绝对力量面前,一切技巧都是浮云 前言 上文 介绍了Http内容协商的一些概念,以及Spring MVC内置的4种协商方式使用介绍.本文主要针对Spring MVC内容协商方式:从步骤.原理 ...
- 【SpringBoot1.x】SpringBoot1.x 启动配置原理 和 自定义starter
SpringBoot1.x 启动配置原理 和 自定义starter 启动配置原理 本节源码 启动过程主要为: new SpringApplication(sources) 创建 SpringAppli ...
- WPF打印原理,自定义打印
一.基础知识 1.System.Printing命名空间 我们可以先看一下System.Printing命名空间,东西其实很多,功能也非常强大,可以说能够控制打印的每一个细节,曾经对PrintDial ...
- 深入了解View实现原理以及自定义View详解
下面几篇文章对View的原理讲的非常详细. Android LayoutInflater原理分析,带你一步步深入了解View(一) Android视图绘制流程完全解析,带你一步步深入了解View(二) ...
- (转)浅谈dedecms模板引擎工作原理及自定义标签
理解织梦模板引擎有什么意义?一方面可以更好地自定义标签.更多在于了解织梦系统,理解模板引擎是理解织梦工作原理的第一步.理解织梦会使我们写php代码时更顺手,同时能学习一些php代码的组织方式. 这似乎 ...
- 贝塞尔曲线:原理、自定义贝塞尔曲线View、使用!!!
一.原理 转自:http://www.2cto.com/kf/201401/275838.html Android动画学习Demo(3) 沿着贝塞尔曲线移动的Property Animation Pr ...
- SpringBoot之旅第六篇-启动原理及自定义starter
一.引言 SpringBoot的一大优势就是Starter,由于SpringBoot有很多开箱即用的Starter依赖,使得我们开发变得简单,我们不需要过多的关注框架的配置. 在日常开发中,我们也会自 ...
随机推荐
- spring4-2-bean配置-11-基于注解
- spring中添加google的guava缓存(demo)
1.pom文件中配置 <dependencies> <dependency> <groupId>org.springframework</groupId> ...
- zookeeper 面试题2 比较乱
Zookeeper是什么框架分布式的.开源的分布式应用程序协调服务,原本是Hadoop.HBase的一个重要组件.它为分布式应用提供一致性服务的软件,包括:配置维护.域名服务.分布式同步.组服务等.应 ...
- 相机IMU融合四部曲(二):误差状态四元数详细解读
相机IMU融合四部曲(二):误差状态四元数详细解读 极品巧克力 前言 上一篇文章,<D-LG-EKF详细解读>中,讲了理论上的SE3上相机和IMU融合的思想.但是,还没有涉及到实际的操作, ...
- maven filter插件只替换了部分变量问题
maven filter简介 maven的resources插件,有一个filter的作用,能够在打包的时候,从特定文件里读取key-value对,替换配置文件中的占位符变量.很多线上线下有不同环境的 ...
- 在linux下使用CMake构建应用程序
本文介绍了一个跨平台的自动化构建系统 CMake 在 linux 上的使用方法. CMake 是一个比 automake 更加容易使用的工具,能够使程序员从复杂的编译连接过程中解脱出来.文中通过一些例 ...
- java Calender类
1.Calender和Date相互转化 public static void main(String[] args) { // TODO Auto-generated method stub Cale ...
- Alpha冲刺 - (9/10)
Part.1 开篇 队名:彳艮彳亍团队 组长博客:戳我进入 作业博客:班级博客本次作业的链接 Part.2 成员汇报 组员1(组长)柯奇豪 过去两天完成了哪些任务 进一步优化代码,结合自己负责的部分修 ...
- Android adb 命令
一.概述 作为一名开发者,相信对adb指令一定不会陌生.那么在手机连接adb后,可通过am命令做很多操作: (1) 拨打电话10086 adb shell am start -a android.in ...
- 再次理解js中的call函数
a.call(b); 网上说明的版本比较多.有的说,是指针替换.有说,将a对象的方法加在b对象执行.官方说:什么对象替换什么对象.反正看了几个版本,尽管有具体的实例,看了我三次都没看懂它的具体含义.看 ...