• 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 一个分类

     1 #import "NSObject+kvc.h"
     2 #import <objc/runtime.h>
     3 @implementation NSObject (kvc)
     4 - (void)xs_setValue:(id)value forKey:(NSString *)key{
     5     //key 需要合法
     6     if (key == nil || key.length == 0) {
     7         return;
     8     }
     9     //一.setter 方法
    10     //调用相关setter方法(capitalizedString 首字母大写)
    11     NSString *setKey = [NSString stringWithFormat:@"set%@:",[key capitalizedString]];
    12     //调用
    13     if ([self respondsToSelector:NSSelectorFromString(setKey)]) {
    14         [self performSelector:NSSelectorFromString(setKey) withObject:value];
    15         return;
    16     }
    17     NSString *setIsKey = [NSString stringWithFormat:@"setIs%@:",[key capitalizedString]];
    18     if ([self respondsToSelector:NSSelectorFromString(setIsKey)]) {
    19         [self performSelector:NSSelectorFromString(setIsKey) withObject:value];
    20         return;
    21     }
    22     
    23     //异常处理方法
    24     if (![self.class accessInstanceVariablesDirectly]) {
    25         NSException *exception = [NSException exceptionWithName:@"XSKVC Exception" reason:@"你返回了NO啊!" userInfo:nil];
    26         @throw exception;
    27         return;
    28     }
    29     //二.成员变量
    30     unsigned int count = 0;
    31     //获取所有成员变量
    32     Ivar *ivars = class_copyIvarList([self class], &count);//解释:在C中,copy new create 在堆区开辟内存空间
    33 //    NSMutableArray *array = [NSMutableArray array];
    34 //    for (int i = 0; i<count; i++) {
    35 //        Ivar ivar = ivars[i];
    36 //        const char *name = ivar_getName(ivar);
    37 //        NSString *keyName = [NSString stringWithUTF8String:name];
    38 //        [array addObject:keyName];
    39 //    }
    40     //_key (按照优先级:_key > _isKey > key > isKey)
    41     for (int i = 0; i<count; i++) {
    42         Ivar ivar = ivars[i];
    43         NSString *keyName = [NSString stringWithUTF8String:ivar_getName(ivar)];
    44         if ([keyName isEqualToString:[NSString stringWithFormat:@"_%@",key]]) {
    45             object_setIvar(self, ivar, value);
    46             free(ivars);
    47             return;
    48         }
    49     }
    50     //_isKey
    51     for (int i = 0; i<count; i++) {
    52         Ivar ivar = ivars[i];
    53         NSString *keyName = [NSString stringWithUTF8String:ivar_getName(ivar)];
    54         if ([keyName isEqualToString:[NSString stringWithFormat:@"_is%@",key.capitalizedString]]) {
    55             object_setIvar(self, ivar, value);
    56             free(ivars);
    57             return;
    58         }
    59     }
    60     //key
    61     for (int i = 0; i<count; i++) {
    62         Ivar ivar = ivars[i];
    63         NSString *keyName = [NSString stringWithUTF8String:ivar_getName(ivar)];
    64         if ([keyName isEqualToString:[NSString stringWithFormat:@"%@",key]]) {
    65             object_setIvar(self, ivar, value);
    66             free(ivars);
    67             return;
    68         }
    69     }
    70     //isKey
    71     for (int i = 0; i<count; i++) {
    72         Ivar ivar = ivars[i];
    73         NSString *keyName = [NSString stringWithUTF8String:ivar_getName(ivar)];
    74         if ([keyName isEqualToString:[NSString stringWithFormat:@"is%@",key.capitalizedString]]) {
    75             object_setIvar(self, ivar, value);
    76             free(ivars);
    77             return;
    78         }
    79     }
    80     
    81     //处理异常
    82     [self setValue:value forUndefinedKey:key];
    83     free(ivars);
    84     
    85 }
  • 相关阅读:
    死锁
    钩子函数和回调函数的区别
    蓝绿部署、滚动发布、灰度发布的介绍以及最佳实践
    小公司的瓶颈
    Modbus协议详解
    windows+jenkin
    Java:简单的多态实例
    一、Kubernetes系列之介绍篇
    Shell脚本自动搭建ipsec环境
    Appium(1):安卓自动化环境搭建 + Android SDK + Appium 环境搭建
  • 原文地址:https://www.cnblogs.com/daxueshan/p/8299182.html
Copyright © 2020-2023  润新知