KVC 原理及自定義實現

一.  setValue: forKey: 賦值過程api

1.首先尋找setter方法(兩個)spa

   - setName:code

   -setIsName:orm

2.而後再尋找成員變量blog

默認 + (BOOL)accessInstanceVariablesDirectly 返回YES;內存

  _key > _isKey > key > isKey get

3. 若是以上步驟沒有找到key,則會報異常; 也能夠重寫方法,防止崩潰string

  -setValue: forUndefinedKey:it

 

二. valueForKey: 取值過程io

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 }
相關文章
相關標籤/搜索