【iOS】KVC

MVC

简介

KVC全称Key-Value-Coding ,中文名称为键码编值,可以通过一个key来访问某一个属性。

KVC提供了一种间接访问其属性方法或者成员变量的机制,可以通过字符串来访问对应的属性方法或成员变量。

他是一个非正式的Protrocol ,提供一种机制来间接访问对象的属性,而不是通过调用Setter、Getter方法 访问。KVO就是基于KVC实现的关键技术之一。

KVC常见的用法

常见的API

objectivec 复制代码
//通过KeyPath(路径)来设值
- (void)setValue:(id)Value forKeyPath:(NSString *)keyPath;
//通过Key来设值
- (void)setValue:(id)Value forKey:(NSString *)key;
//通过keyPath来取值
- (id)valueForkeyPath:(NSString *)keyPath;
//通过Key来取值
- (id)valueForkey:(NSString *)key;

Key与KeyPath

Key:只能接受当前类所具有的属性,不管是自己的,还是从父类继承过来的。

KeyPath:除了能接受当前类的属性,还可以接受当前类属性的属性,即可以接受一个关系链。

下面举两个例子来说明:

在上面图片中,我们可以看到常见API的使用方法。

KVC的强大功能

批量存取值功能

批量存值操作:

KVC中,可以根据一组给定的key来获取到一组Value,并且以字典的形式返回。

objectivec 复制代码
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;

批量赋值操作:

//通过该方法允许通过一个字典一次性设置多个属性的值,不需要逐个去使用- (void)setValue:(id)Value forKey:(NSString *)key;。

objectivec 复制代码
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;

举例说明:

objectivec 复制代码
#import <Foundation/Foundation.h>
#import "Person.h"


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person* p1 = [[Person alloc] init];
        
        [p1 setValue:@"eric" forKey:@"name"];
        [p1 setValue:@"19" forKey:@"age"];
        [p1 setValue:@"man" forKey:@"sex"];
        NSDictionary* dic = [p1 dictionaryWithValuesForKeys:@[@"name", @"age", @"sex"]];
        NSLog(@"%@", dic);
        NSDictionary* dic1 = @{@"name":@"jack", @"age":@30, @"sex":@"women"};
        Person* p2 = [[Person alloc] init];
        [p2 setValuesForKeysWithDictionary:dic1];
        NSLog(@"name = %@, age = %@, sex = %@", p2.name, p2.age, p2.sex);
    }
    return 0;
}

打印结果:

字典转化模型

如果model和dic不匹配,可以重写方法-(void)setValue:(id)value forUndefinedKey:(NSString *)key.

objectivec 复制代码
#import "Person.h"

@implementation Person

- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
    if([key isEqualToString:@"sex"]) {
        self.sex = (NSString*) value;
    }
}

@end

KVC的底层原理

赋值原理

结合上图,来看看KVC赋值的原理:

  • 首先会查找setKey、_setKey方法,如果找到,那么直接调用方法赋值。
  • 如果没有找到方法,则会查看+ (BOOL)accessInstanceVariablesDirectly(控制是否可以直接访问实例变量)是否为YES(默认为YES)。
  • 若为YES,则会按照_key,_isKey,key,isKey的顺序查找成员变量,如果找到则会直接给成员变量赋值,找不到就抛出NSUnknownException异常。
  • 若为NO,则会调用setValue:ForUndefinedKey:并且抛出NSUnknownException异常。

取值原理

结合上图,来看看KVC取值的原理:

  • 首先会按照getKey,key,isKey,_key的混序查找方法,如果找到方法,直接调用方法。
  • 若未找到方法,则查看+ (BOOL)accessInstanceVariablesDirectly(控制是否可以直接访问实例变量)是否为YES(默认为YES)。
  • 若返回为YES,则按照_key,_isKey,key,isKey的顺序去查找成员变量,如果找到成员变量,则直接取值,未找到则抛出NSUnknownException异常。
  • 若为NO,则会调用valueForundefinedKey:并且抛出NSUnknownException异常。
相关推荐
传奇开心果编程17 小时前
【Compose Multiplatform 跨端开发学与练】第7课 平台适配与互操作
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程1 天前
【Compose Multiplatform 跨端开发学与练】第5课 网络与数据层
android·网络·学习·ui·ios·kotlin·composer
茶底世界之下1 天前
视频预览切换为何会闪回旧帧:用 generation + mode identity 管住异步回调
ios·swift
老李IT笔记1 天前
从备份恢复会把管理状态带回来吗:iOS 27 之后答案变了|MDM.Plus
ios·智能手机
谢亮_vipxieliang1 天前
Go 接口设计原则核心知识点
开发语言·ios·golang
andyweike1 天前
iOS语法原理
macos·objective-c·cocoa
黑妹天下第一乖1 天前
第 10 讲:阿加犀 AidVoice 端侧语音交互与语音识别实战
图像处理·人工智能·数码相机·opencv·交互·语音识别·xcode
Hello_Pyhx1 天前
iPhoneMirror:把 iPhone 接入 Windows,先分清投屏与反控
windows·ios·iphone
茶底世界之下1 天前
类型擦除之后,Metal 滤镜组合为什么不能只执行一个 Filter?
ios·swift
传奇开心果编程2 天前
【SwiftUI提高练中学】第8课 网络层架构:拦截器、重试、缓存与离线优先
学习·macos·ui·ios·swiftui