今天无意间了解到KVC(Key-Value-Coding)(且并没有了解到KVO(Key-Value-Observe)的情况下),看了半天不知道它的作用何在,通过间接访问属性的方法,这不多此一举么?而且通过 Key 来访问,很容易打错字啊!
因为会 Java 反射的缘故,发觉 KVC 其实还蛮像的,然后我突发奇想,Java 反射能够不通过 set 方法更改属性值,那KVC呢?
当然,它也可以,那么一个对象的属性值为 readonly 时,它也能改变该属性值么?如果能,那它意义就重大了!
下面我就做个实验来验证看看!
首先简单介绍一下先。
KVC,即是指 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性。而不是通过调用Setter、Getter方法访问。KVO 就是基于 KVC 实现的关键技术之一。
KVC的常用方法:
//根据key读取对象的属性值
- (id)valueForKey:(NSString *)key;
//设置某个key(属性)的值为value
- (void)setValue:(id)value forKey:(NSString *)key;
很简单的两个方法,一个相当于 getter,一个相当于 setter。
注意:
(1). key的值必须正确,如果拼写错误,会出现异常(2). 当key的值是没有定义的,valueForUndefinedKey:这个方法会被调用,如果你自己写了这个方法,key的值出错就会调用到这里来
(3). 因为类key反复嵌套,所以有个keyPath的概念,keyPath就是用.号来把一个一个key链接起来,这样就可以根据这个路径访问下去
(4). NSArray/NSSet等都支持KVC
好,基础普及到这里。下面实验开始!
1.新建一个普通的工程。
2.新建一个类,取名为 TestKVC,类里面声明一个属性 name,注意该属性是只读的(readonly)。
#import <Foundation/Foundation.h>
@interface TestKVC : NSObject
@property(nonatomic, readonly) NSString *name;
@end
3.在.m文件里面的初始化定义该属性。
#import "TestKVC.h"
@implementation TestKVC
- (instancetype)init
{
self = [super init];
if (self) {
_name = @"APP"; //初始化名称为“APP”,记住咯!
}
return self;
}
@end
4.测试 KVC 是否能够改变该值。(我在 ViewController 的 viewDidLoad 方法里面写的如下代码)
TestKVC *test = [[TestKVC alloc] init];
NSLog(@"name is %@", test.name);
[test setValue:@"AZZ" forKey:@"name"];
NSLog(@"new name is %@", test.name);
5.有图有真相
看到最下面的打印没有?name 已经被我改成“AZZ”了!
6.直接更改该属性试试(结果当然是不行!~)
so,实验成功!
总结:即使属性被设置为了 readonly ,通过 KVC 还是可以更改该属性的值!
如果你有任何问题,欢迎留言告诉我!~