一.  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 原理及自定义实现的更多相关文章

  1. 【原】iOS学习之KVC原理

    1. KVC的实现原理 遍历字典里面所有的key,以name为例 去模型中查找有没有setName:方法,有就直接调用赋值 假如没有找到setName:方法,就会继续查找有没有_name属性,有就_n ...

  2. JAVA之旅(二十五)——文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine

    JAVA之旅(二十五)--文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine 我们继续IO上个篇 ...

  3. Spring MVC内容协商实现原理及自定义配置【享学Spring MVC】

    每篇一句 在绝对力量面前,一切技巧都是浮云 前言 上文 介绍了Http内容协商的一些概念,以及Spring MVC内置的4种协商方式使用介绍.本文主要针对Spring MVC内容协商方式:从步骤.原理 ...

  4. 【SpringBoot1.x】SpringBoot1.x 启动配置原理 和 自定义starter

    SpringBoot1.x 启动配置原理 和 自定义starter 启动配置原理 本节源码 启动过程主要为: new SpringApplication(sources) 创建 SpringAppli ...

  5. WPF打印原理,自定义打印

    一.基础知识 1.System.Printing命名空间 我们可以先看一下System.Printing命名空间,东西其实很多,功能也非常强大,可以说能够控制打印的每一个细节,曾经对PrintDial ...

  6. 深入了解View实现原理以及自定义View详解

    下面几篇文章对View的原理讲的非常详细. Android LayoutInflater原理分析,带你一步步深入了解View(一) Android视图绘制流程完全解析,带你一步步深入了解View(二) ...

  7. (转)浅谈dedecms模板引擎工作原理及自定义标签

    理解织梦模板引擎有什么意义?一方面可以更好地自定义标签.更多在于了解织梦系统,理解模板引擎是理解织梦工作原理的第一步.理解织梦会使我们写php代码时更顺手,同时能学习一些php代码的组织方式. 这似乎 ...

  8. 贝塞尔曲线:原理、自定义贝塞尔曲线View、使用!!!

    一.原理 转自:http://www.2cto.com/kf/201401/275838.html Android动画学习Demo(3) 沿着贝塞尔曲线移动的Property Animation Pr ...

  9. SpringBoot之旅第六篇-启动原理及自定义starter

    一.引言 SpringBoot的一大优势就是Starter,由于SpringBoot有很多开箱即用的Starter依赖,使得我们开发变得简单,我们不需要过多的关注框架的配置. 在日常开发中,我们也会自 ...

随机推荐

  1. jsp页面数据分页模仿百度分页效果

    <%@page import="web09.shop.DBUtil"%> <%@page import="java.sql.ResultSet" ...

  2. p4475 巧克力王国

    传送门 分析 我们多维护一个值,代表某个点子树中所有点的权值和 于是如果某个点它的min和max乘a(/b)的值小于范围则直接把整个子树都加进去 估价函数就是这个点的子树中的理论最小值 代码 #inc ...

  3. cJSON结构体构建

    cJSON结构体构建 一:cJSON的构建. int create_objects() { cJSON *root, *fmt, *img, *thm, *fld; char *out; int i; ...

  4. Reading——简约至上

    读书感言: 简约至上——Giles Colborne,我去,这是哪里来的渣书,通篇都是泛泛而谈,实在受不鸟了> <,没学到啥实质性的东西,论述一大堆.!!!还姐的20多块钱.最讨厌这样的书 ...

  5. U盘安装RedHat linux 5.3

    U盘安装RedHat linux 5.3 1.下载rhel-5.3-server-i386-dvd.iso文件: 2.下载绿色版UltraISO软件: 3.将rhel-5.3-server-i386- ...

  6. 42 :809*x=800*x+9*x+1

    题目:809*x=800*x+9*x+1(去掉最后的1有解)其中x代表的两位数,8*x的结果为两位数,9*x的结果为3位数.求x代表的两位数,及809*x后的结果(两种方法实现) public cla ...

  7. 创建EDM

    在学习linq过程中,我们难免会要创建EDM,这里简单的介绍一下EDM的创建过程 图示如下: 1.右击→添加→新建项→数据→Ado.net实体数据模型 选择适当的数据库,表后点击完成,vs中会自动生成 ...

  8. Mac上phantomjs装了不能用的解决

    下了,装了.然后整这句命令: phantomjs --version 直接报错.. 查了半天的官方文档,居然连个毛线都么找到.终于...墨迹到了一个方法,就抱着试一试的心态在terminal里输入了这 ...

  9. 移动距离——第六届蓝桥杯C语言B组(省赛)第八题

    原创  问题描述: 移动距离 X星球居民小区的楼房全是一样的,并且按矩阵样式排列.其楼房的编号为1,2,3...当排满一行时,从下一行相邻的楼往反方向排号.比如:当小区排号宽度为6时,开始情形如下: ...

  10. JavaScript - this详解 (一)

    侃侃JavaScript中的this this为何如此多变? this总是跟它的执行上下文有关,而在JavaScript总会有开辟新的执行上下文的东西,比如函数,所以,this才如此的变化. 执行环境 ...