淄博信息网:KVC解说

admin/2020-04-10/ 分类:科技/阅读:

今天趁着项目bug修复完了,来解说一下OC知识的另一个手艺点-KVC!针对KVC,解说两个知识点

  • 通过KVC修改属性会触发KVO么?
  • KVC的赋值历程是怎样的?原理是什么?
  • KVC的取值历程是怎样的?原理是什么?

 

一、问:通过KVC修改属性会触发KVO么?

答:会触发KVO

建立工程项目TestKVO,ZXYPerson类有一个属性age,在控制器ViewController中添加属性考察者KVO,项目代码如下

@interface ViewController ()
@property(nonatomic,strong) ZXYPerson
*p; @end

@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; _p = [[ZXYPerson alloc]init]; _p.age = 10; [_p addObserver:self forKeyPath:@"age" options: NSKeyValueObservingOptionNew context:nil]; [_p setValue:@12 forKeyPath: @"age"]; } -(void)dealloc { [_p removeObserver:self forKeyPath:@"age"]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{ NSLog(@"*********%@", change); }

上面橙色文字通过KVC方式更改属性的值,将上面代码运行效果如下:

 

通过上面发现setValue:forKeyPath触发了KVO,同理发现setValue:forKey也会触发KVO,然则这两个方式有什么区别呢?

setValue:forKeyPath会一层一层的(沿着路径)向下找,然而setValue:forKey并不会这样!(若是ZXYPerson养了一只猫,猫有age属性 ,通过"_p.cat.age"设置应该用setValue:forKeyPath,不能用setValue:forKey

思索: 为什么KVC更改属性值会触发KVO?那就需要解说下面知识。

 

二、问:KVC的赋值历程是怎样的?原理是什么?

 setValue:forKey:的原理

accessInstanceVariablesDirectly方式的默认返回值是YES

下面逐一验证上面的顺序:

 验证setValue:forkey挪用历程不需要用到KVO,去除多余的代码之后,简化成如下:

#import "ViewController.h" #import "ZXYPerson.h" @interface ViewController () @property(nonatomic,strong) ZXYPerson *p; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; _p = [[ZXYPerson alloc]init]; [_p setValue:@12 forKeyPath: @"age"]; } @end #import "ZXYPerson.h" @implementation ZXYPerson - (void) setAge:(int)age { NSLog(@"挪用了setAge方式"); } - (void) _setAge: (int)age { NSLog(@"挪用了_setAge方式"); } @end

去除了age属性的声明,看看KVC赋值的前期历程(根据setKey, _setKey方式走)

 同时写了两个方式,优先挪用setAge方式,若是将setAge方式注释掉

 注释掉setAge方式后,久挪用了_setAge方式,证实了KVC的前期赋值情形!

 

若是两个方式都没有实现,此时KVC会accessInstanceVariablesDirectly方式,返回Yes代表可以直接接见成员变量,反之不能接见成员变量!

若是返回为Yes,会根据_key、_isKey、key、isKey成员属性举行赋值

此时像上面的代码加入这四个成员变量,如下(条件accessInstanceVariablesDirectly方式返回Yes)

@interface ZXYPerson : NSObject { @public int _age; int _isAge; int age; int isAge; } @end

加入上述代码,运行

 首先给_age赋值,当四个成员变量同时泛起,若是将int _age成员变量注释掉,如下:

发现当_age注释掉之后,优先给_isAge赋值,优先级仅次于_age,若是将_isAge注释掉之后

 发现给age赋值,同理将age成员变量注释掉之后

 最后给isAge赋值,相符了上述setValue:forkey的接见属性的优先级 _key > _isKey > key > isKey的顺序

 

若是这四个成员变量都没有了,就会报异常

 通过上面讲述知道setValue:forKey会触发KVO

[_p setValue:@12 forKeyPath: @"age"]内部挪用相当于

[p willChangeValueForKey @"age"]

p->_age = 12;

[p didChangeValueForKey @"age"]

以是会触发KVO

以上就是setValue:forKey的赋值所有历程,希望人人再看看上述图,下面讲述KVC若何取值?

 

三、问: KVC的取值历程是怎样的?原理是什么?

valueForKey:的原理

 

 下面逐一验证上面的顺序:

@interface ZXYPerson : NSObject{ @public int _age; } @implementation ZXYPerson - (int)getAge { return 11; } - (int)age { return 12; } - (int)isAge { return 13; } - (int)_age { return 14; } @end @interface ViewController () @property(nonatomic,strong) ZXYPerson *p; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; _p = [[ZXYPerson alloc]init]; _p->_age = 10; NSLog(@"******%@",[_p valueForKey:@"age"]); } @end

看看KVC取值的前期历程(根据getAge > age > isAge > _age 方式走)

 

当有四个方式时,会优先挪用getAge方式,如上面一样打印出11,挪用了getAge方式!若是把getAge()方式注释掉,运行代码:

 

 将getAge()方式注释掉后,挪用了age方式,验证了getAge > age !若是把age方式注释掉

 

将getAge()和age()方式注释掉后,挪用了isAge()方式,验证了getAge > age > isAge !若是把isAge()方式注释掉 

 

将getAge()和age()方式以及isAge()注释掉后,挪用了_age()方式,验证了getAge > age > isAge > _age! 

若是四个方式都没有实现,此时KVC会看accessInstanceVariablesDirectly方式,返回Yes代表可以直接查找成员变量,反之不能查找成员变量!

若是返回为Yes,会根据_key、_isKey、key、isKey成员属性顺序查找成员变量

此时像上面的代码加入这四个成员变量,如下(条件accessInstanceVariablesDirectly方式返回Yes,去除四个方式)

 @public int _age; int _isAge; int age; int isAge;

加入了四个成员变量,控制器ViewController加入设置属性的四个值的

 _p->_age = 11; _p->_isAge = 12; _p->age = 13; _p->isAge = 14;

考察成员变量的查找顺序!验证_key、_isKey、key、isKey

 

 ZXYPerson有四个成员变量,当向着上面代码誊写,运行代码结论是11,对应着_age这个成员变量,以是优先取值_age!当将 _age成员变量注释掉以及赋值注释掉后

 

发现运行效果为12,对应的效果时_isAge, 得出结论 _age > _isAge! 继续将_isAge成员变量注释掉以及赋值_isAge如下:

 

 发现运行效果为13,对应的效果时age, 得出结论 _age > _isAge > age! 继续将age成员变量注释掉以及赋值age如下:

 

 发现运行效果为14,对应的效果时isAge, 得出结论 _age > _isAge > age > isAge! 继续将isAge成员变量注释掉以及赋值isAge如下:

 若是都注释掉,会报异常valueForUndefinedKey错误!

以上就是valueForKey的取值所有历程,希望人人再看看上述图回首KVC若何取值!

 

上述就是KVC的基本内容,希望对人人有所辅助,可以关注博客会实时更新,谢谢!!!

,

阳光在线

阳光在线www.kingtaowang.com(原诚信在线)现已开放阳光在线手机版下载。阳光在线游戏公平、公开、公正,用实力赢取信誉。

TAG:
阅读:
广告 330*360
广告 330*360
Sunbet_进入申博sunbet官网
微信二维码扫一扫
关注微信公众号
新闻自媒体 Copyright © 2002-2019 Sunbet 版权所有
二维码
意见反馈 二维码