KVC和KVO底层原理

来源:互联网 发布:吸毒到底有多恐怖 知乎 编辑:程序博客网 时间:2024/05/16 09:16
KVC和KVO想必都熟知的一个名词,观察者模式,而KVO是基于KVC的,那么KVC到底是个什么,KVO又是什么,那么它们之间是怎么关联的。
    当你了解KVC机制,会恍然大悟,只要知道一个UI的结构,就能对他做任意的修改。而KVO是观察者模式的一种实现,对对象属性监听能达到一个高性能处理,所以了解KVC和KVO的机制原理还是很重要的。
一、首先先讲KVC,KVC简称KeyValueCoding,是一个基于NSKeyValueCoding非正式协议的机制,就是直接通过key值对对象的属性进行存取操作,而不是通过明确的存取方法,简而言之也就是一系列规则和方法进行的存取操作,那接下来深入了解KVC在底层做了些什么。
:NSObject是定义了KVC的,所以继承NSObject的对象都支持KVC,基本上所有的OC对象都支持KVC。
1、 首先我们了解取值功能,MyObject对象代码如下:
 @interface MyObject : NSObject @property (nonatomic, strong)NSString *name;
 @end

我们对该对象的name进行取值
myObject = [[MyObject alloc] init]; 

myObject.name = @"八点钟";
NSLog(@"%@", myObject.name);
当执行myObject.name时,系统自动会执行- (NSString*)name方法,这个方法在property建立的时候,系统会默认生成,也会对应的生成setName方法。
2、我们换以一种形式来访问,在没有主动建立property的情况下,MyObject对象代码如下:
@interface MyObject : NSObject
@end

我们对该对象的name进行取值
myObject = [[MyObject alloc] init];

NSLog(@"%@",[myObject valueForKey:@"name”]);
当执行[myObject valueForKey:@"name"]时,系统就会根据key来进行一个搜索,那么KVC执行规则是:搜索-(NSString)getName方法,- (NSString)name方法,- (NSString*)isName方法,这三个方法的先后顺序来查找,如果有,则执行相应的方法,(这是按NSString类型的查找规则)。
如果没有则继续找,因为key:@"name",系统也不知道查找的name是什么类型的,那么系统会按照其他数据类型的方式继续找,如数组NSArray查找方式是会找这两个方法
-(NSUInteger)countOfName 

-(id)objectInNameAtIndex:(NSUInteger)index
如果找到了就执行。依此类推还有其他数据类型的查找方式,不一一例举出来了,重点是了解有这么一个过程,KVC原理。
如果按照KVC规则没有查找到相应的方法则会调用valueForUndefinedKey:方法,系统直接抛出异常,程序Crash, 我们可以重写valueForUndefinedKey这个方法,则不会导致系统抛出异常,防止程序奔溃。
那么KVC还提供了valueForKeyPath:等这些取值方法。注意如果是BOOL或者int等值类型,会做NSNumber转换。

讲了这么多,来一波代码,看现象:(依次注释MyObject类里面的方法来看效果就一目了然,代码简单,磨起键盘吧,高手是敲出来的,背后都有一部撸的辛酸史,实践出真知,代码撸起来)


二、接下来我们来研究存的操作(修改对象属性)
property的上面已经提到了,来看另一种方式setValue:forKey或setValue:forKeyPath等方法。
对象代码:(MyObjectTwo类没有定义任何属性)
@interface MyObjectTwo :NSObject

@end
执行代码
myObjectTwo = [[MyObjectTwoalloc] init];

[myObjectTwo setValue:@"八点种学院" forKey:@"name"];
调用setValue:forkey:代码时,底层的执行机制:程序会去找setName:属性值方法,如果没有找到setName:方法,KVC机制会检查(BOOL)accessInstanceVariablesDirectly方法有没有返回YES,系统默认是返回YES的,但我们可以重写该方法,返回NO,如果是返回NO,没找到setName方法,那么系统就会执行setValue:ForUndefineKey:方法,系统抛出异常,程序Crash。返回YES,继续搜索类里面成员变量,搜索顺序依次是_name、_isName、name、isName,如果找了相应变量,就停止寻找,对该变量进行修改。
动起手来,看机制,一切尽在撸


注意:当对NSDictionary对象使用KVC时,valueForKey:和objectForKey:效果一样。
可以看出利用KVC可以修改类的私有变量,可以修改IOS隐藏一些属性,如UITextField的placeHolderText默认style在需求中达不到要求,我们可以直接通过KVC快速定义自己的style,代码如下:
[textField setValue:[UIColor redColor] forKeyPath:@"placeholderLabel.textColor"];
如果你了解一个UI的内部结构,你可以通过KVC可以改变系统默认的任何效果,KVC是不是很强大。
本文简单的讲述了KVC的内部原理,如果一个框架没有KVC机制的时候,我们就可以简单实现自己的KVC,一个程序猿追求的应该不是对工具的使用,而是理解原理机制,创造工具,那么你就是牛B的。编程的目的是希望写出高效率高性能的东西,而机制对任何一种语言都实用,所以常说语言是相通的,你精通一门就精通大部分语言了。
更多复杂KVC使用方式期待后续;夜深,下篇再继续结合KVC来讲解KVO

原创粉丝点击