-
KVC 的全称是 Key-Value Coding,俗称“键值编码”,可以通过一个 key 来访问某个属性
-
常见的 API 有:
//设置值 - (void)setValue:(id)value forKeyPath:(NSString *)keyPath; - (void)setValue:(id)value forKey:(NSString *)key; //获取值 - (id)valueForKeyPath:(NSString *)keyPath; - (id)valueForKey:(NSString *)key;
-
简单复习KVC的使用,示例代码如下:
#import <Foundation/Foundation.h> @interface Person : NSObject @property (nonatomic,assign) int age; @end @implementation Person @end int main(int argc, char * argv[]) { @autoreleasepool { // Setup code that might create autoreleased objects goes here. Person *p = [[Person alloc] init]; // [p setValue:@10 forKey:@"age"]; [p setValue:@10 forKeyPath:@"age"]; NSLog(@"%d",p.age); } return 0; }
输出结果如下:
10
-
在 iOS 的 KVC(Key-Value Coding) 中,setValue:forKey 和 setValue:forKeyPath 都可以完成属性的赋值操作,那他们的区别是什么呢?
(1)setValue:forKey 是对某个对象的某个属性进行赋值,其中键是属性名。它只能访问到当前对象的继承体系中已定义的属性,而不能访问到动态添加的属性或成员变量;
(2)setValue:forKeyPath 是使用一个点语法来指定属性的层级路径进行赋值操作。它除了可以访问当前对象的属性之外,还可以访问属性所嵌套的其他对象的属性,支持对嵌套属性进行递归赋值操作。例如,如果想给一个人对象(Person)的子对象(Address)的属性(city)进行赋值操作,可以使用 setValue:forKeyPath 来指定完整的路径“address.city”,而不需要一步步地访问到这个属性。
需要注意的是,使用 KVC 进行属性赋值时,虽然可以通过键值编码的方式,简单地统一了属性和方法的访问,但是需要确保键名和键路径的正确性和安全性,避免破坏对象的内部状态并导致未知的错误。
-
-
相关问题
-
通过 KVC 修改属性会触发 KVO 么?
会触发 KVO。验证:可以重写类中的 willChangeValueForKey: 和 didChangeValueForKey: 这两个方法。可以发现,KVC 的赋值操作,底层在对成员变量赋值之前会调用 willChangeValueForKey: 的方法,然后对成员变量赋值;接着再调用 didChangeValueForKey: 方法。didChangeValueForKey: 方法内部会通知监听器调用监听方法。
-
KVC 的赋值和取值过程是怎么样的?原理是什么?
(1)setValue:forKey: 的赋值原理如下:
- 先判断是否存在 setKey: 、_setKey: 的方法,按此顺序查找方法,如果能找到,则直接传递参数,调用方法;
- 如果找不到,则查看 accessInstanceVariablesDirectly 方法的返回值(该方法的返回值默认是返回YES),如果该方法的返回值是 no,则意味着不允许直接访问成员变量,此时程序直接抛出异常,会调用 setValue:forUndefinedKey: 方法;
- 如果 accessInstanceVariablesDirectly 方法的返回值是 Yes,则会按照 _key、 _isKey、key、isKey 的顺序查找成员变量,如果能找到成员变量,则直接赋值;
- 如果找不到成员变量,则程序抛出异常,会调用 setValue:forUndefinedKey: 方法;
(2)valueForKey: 的取值过程原理如下:
- 按照 getKey、key、isKey、_key 顺序查找方法。如果能找到了方法则直接调用方法;
- 如果找不到,则查看 accessInstanceVariablesDirectly 方法的返回值(该方法的返回值默认是返回YES),如果该方法的返回值是 no,则意味着不允许直接访问成员变量,此时程序直接抛出异常,会调用NSUnknownKeyException;
- 如果 accessInstanceVariablesDirectly 方法的返回值是 Yes,则会继续按照 _key、 _isKey、key、isKey 顺序查找成员变量。
- 如果找不到成员变量,则程序抛出异常,会调用 setValue:forUndefinedKey: 方法;
-
网友评论