KVC和KVO底层原理

了解更多iOS底层原理知识,关注腾讯课堂八点钟学院iOS高级开发
iOS学习交流QQ群431449751

KVC和KVO想必都熟知的一个名词,采用观察者模式,那么KVC到底是个什么,KVO又是什么,它们之间是怎样关联的,一起来解决这些疑惑。

像我们银行卡bankCard的余额变动,会及时通知给用户,这种场景就运用了观察者模式,达到了系统的高效高性能处理;当你了解KVC机制,会恍然大悟,只要知道一个UI的结构,就能对他做任意的修改,所以了解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”]时,我们没有定义属性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类里面的方法来看效果就一目了然,代码简单,磨起键盘吧,高手是敲出来的,背后都有一部撸的辛酸史,实践出真知,代码撸起来)

KVC和KVO底层原理_第1张图片
KVC和KVO底层原理_第2张图片

二、接下来我们来研究存的操作(修改对象属性)

property的上面已经提到了,来看另一种方式
setValue:forKey或setValue:forKeyPath等方法。

对象代码:(MyObjectTwo类没有定义任何属性)

@interface MyObjectTwo :NSObject
@end

执行代码

myObjectTwo = [[MyObjectTwoalloc]init];
[myObjectTwo setValue:@"八点种学院" forKey:@"name"];

调用setValue:forkey:代码时,系统没有自定属性name,那么底层会怎么做呢, 系统执行的操作:
系统会去找setName:属性值方法,如果没有找到setName:方法,KVC机制会检查(BOOL)accessInstanceVariablesDirectly方法有没有返回YES,系统默认是返回YES的,但我们可以重写该方法,返回NO,如果是返回NO,没找到setName方法,那么系统就会执行setValue:ForUndefineKey:方法,系统抛出异常,程序Crash。返回YES,继续搜索类里面成员变量,搜索顺序依次是_name、_isName、name、isName,如果找了相应变量,就停止寻找,对该变量进行修改。

动起手来,看机制,一切尽在撸

KVC和KVO底层原理_第3张图片
KVC和KVO底层原理_第4张图片

注意:当对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

了解更多IOS底层原理知识请关注腾讯课堂八点钟学院IOS高级开发
https://ke.qq.com/course/171725
IOS学习交流QQ群:431449751

你可能感兴趣的:(IOS)