一.  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. C 和 CPP 混合代码cmath编译出错

    Visual Studio会将cmath内的一些列函数报错 解决方式:项目->属性->配置属性->C/C++ ->高级->编译为->选择编译为C++代码即可

  2. ServiceStack.redis用法

    using System; using System.Collections.Generic; using ServiceStack.Redis; namespace SysBuild { class ...

  3. appium_server_v1.4.16版本不适配android7.0系统,运行报错“Attempt to re-install io.appium.settings without first uninstalling”

    要解决的问题:appium在androidV7.0系统上运行时报错 Failure [INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install io.a ...

  4. [C++] inline function

    trap #define GET3(N)  N*N*N GET3(1+2) :  1+2*1+2*1+2 = 7

  5. mvc注解验证

    前端: @{ Layout = null;}@using System.Activities.Expressions@model MvcApplication1.Models.News<!DOC ...

  6. modifiers标量调节器插件的定义和使用

    在插件目录plugins里新建文件 modifier.插件名.php文件(如 modifier.插件名.php)例:function smarty_modifier_test($utime, $for ...

  7. PHP json_encode中文unicode转码问题

    用PHP的json_encode来处理中文的时候, 中文都会被编码, 变成不可读的, 类似”\u***”的格式,如果想汉字不进行转码,这里提供三种方法 1.升级PHP,在PHP5.4, 这个问题终于得 ...

  8. Hibernate查询对象所有字段,单个字段 ,几个字段取值的问题

    HQL 是Hibernate Query Language的简写,即 hibernate 查询语言:HQL采用面向对象的查询方式.HQL查询提供了更加丰富的和灵活的查询特性,因此Hibernate将H ...

  9. page next page prev

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  10. GitHub 出现这样的问题怎么办

    一开始以为是被墙,憋个半死. 后来自己好了(大概过了一上午),虚惊一场.