美文网首页
iOS-KVC篇

iOS-KVC篇

作者: MirL | 来源:发表于2021-06-28 15:31 被阅读0次

一、前言

KVC(Key-value coding)键值编码,是对NSObjcet的扩展,分类名为 : NSKeyValueCoding

二、常用的方法说明

// 1、将键字符串key所对应的属性的值设置为value。不能设定属性值时,将会引起接收器调用方法2
- (void)setValue:(nullable id)value forKey:(NSString *)key

// 2、当属性值设置失败,调用此方法
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key

// 3、返回标识属性的键字符串所对应的值。如果获取失败,将会引起接收器调用方法4
- (nullable id)valueForKey:(NSString *)key

// 4、取值失败,调用此方法
- (nullable id)valueForUndefinedKey:(NSString *)key

// 5、在键字符串key所对应的"标量"型属性值设为nil,调用此方法,并抛出NSInvalidArgumentException异常(可demo测试)
- (void)setNilValueForKey:(NSString *)key


// 6、默认返回值YES,代表如果没有找到Set方法的话,会按照_key,_iskey,key,iskey的顺序搜索成员,设置成NO就不这样搜索
+ (BOOL)accessInstanceVariablesDirectly

标量 : 属性中的单纯的数值(整数、实数、布尔值等)

在赋值的时候
如果是结构体,必须包装成NSValue实例
如果是标量型属性,必须包装成NSNumber实例

二、setValue:forKey:底层原理

setValue:forKey:

原理如下:

  1. 先找相关方法 set<Key>:_set<Key>:setIs<Key>:,如果有,优先调用setter方法完成赋值(注意:set后面的键的第一字字母必须是大写!!)
  2. 如没有找到相关方法 + (BOOL)accessInstanceVariablesDirectly,判断是否可以直接方法成员变量
  3. 如果判断是NO,直接执行KVC的setValue:forUndefinedKey:(系统抛出异常,未定义key)
  4. 如果判断是YES,继续找相关的_<key>_is<Key><key>is<Key>
  5. 方法或成员 都不存在,setValue:forUndefinedKey:方法,默认抛出异常

三、valueForKey:底层原理

valueForKey:

原理如下:

  1. 先找相关方法 get<Key>:Key:countOfKey, objectInKeyAtIndex
  2. 如没有找到相关方法+ (BOOL)accessInstanceVariablesDirectly,判断是否可以直接方法成员变量
  3. 如果上面判断为NO 直接执行KVC的setValue:forUndefinedKey:(系统抛出异常,未定义key)
  4. 如果判断是YES 继续找相关的_<key>_is<Key><key>is<Key>
  5. 方法或成员 都不存在,setValue:forUndefinedKey:方法,默认抛出异常

四、KVC 为什么能能够触发 KVO

KVC 只所以能够触发 KVO,那是因为 在 KVC 底层有手动触发 KVO的代码,在前面的例子添加方法 willChangeValueForKeydidChangeValueForKey可得到验证。

[person willChangeValueForKey:@"age"];
person->_age = 2;
[person didChangeValueForKey:@"age"];

五、使用场景

1、修改系统控件的样式

UITextField没有提供修改placeholder样式的API,但KVC可以访问类的私有属性,我们可以借助这一特性来修改其样式,但是目前版本已经被禁用了

[self.textField setValue:UIColor.redColor
              forKeyPath:@"_placeholderLabel.textColor"];

2、字典模型互转

@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@end

@implementation Person
- (NSString *)description {
    return [NSString stringWithFormat:@"name:%@, age:%zd", _name, _age];
}
@end

- (void)viewDidLoad {
    [super viewDidLoad];

    NSDictionary *dict = @{@"name" : @"zhangSan",
                           @"age"  : @(1)};
    
    Person *person = [Person new];
    [person setValuesForKeysWithDictionary:dict];
    NSLog(@"字典转模型---%@", person);
    
    NSDictionary *newDict = [person dictionaryWithValuesForKeys:@[@"name", @"age"]];
    NSLog(@"模型转字典---%@", newDict);
}

// 打印
字典转模型---name:zhangSan, age:1
模型转字典---{
    age = 1;
    name = zhangSan;
}

3、操作集合

NSArray *array = @[@"china", @"english", @"american"];

NSArray *capArray = [array valueForKey:@"capitalizedString"];
NSLog(@"capitalizedString---%@", capArray);
    
NSArray *lengthArray = [array valueForKeyPath:@"capitalizedString.length"];
NSLog(@"capitalizedString.length---%@", lengthArray);

// 打印
capitalizedString---(
    China,
    English,
    American
)
capitalizedString.length---(
    5,
    7,
    8
)

相关文章

  • iOS-KVC(一)基本使用

    iOS-KVC(一)基本使用iOS-KVC(二)内部赋值深层次原理iOS-KVC(三)内部取值深层次原理iOS-K...

  • iOS-KVC(二)内部赋值深层次原理

    iOS-KVC(一)基本使用iOS-KVC(二)内部赋值深层次原理iOS-KVC(三)内部取值深层次原理iOS-K...

  • iOS-KVC(五)容器类

    iOS-KVC(一)基本使用iOS-KVC(二)内部赋值深层次原理iOS-KVC(三)内部取值深层次原理iOS-K...

  • iOS-KVC(四)常见异常处理

    iOS-KVC(一)基本使用iOS-KVC(二)内部赋值深层次原理iOS-KVC(三)内部取值深层次原理iOS-K...

  • iOS-KVC(六)正确性验证

    iOS-KVC(一)基本使用iOS-KVC(二)内部赋值深层次原理iOS-KVC(三)内部取值深层次原理iOS-K...

  • iOS-KVC(三)内部取值深层次原理

    iOS-KVC(一)基本使用iOS-KVC(二)内部赋值深层次原理iOS-KVC(三)内部取值深层次原理iOS-K...

  • iOS-KVC(八)常见使用

    iOS-KVC(一)基本使用iOS-KVC(二)内部赋值深层次原理iOS-KVC(三)内部取值深层次原理iOS-K...

  • iOS-KVC(七)字典相关

    iOS-KVC(一)基本使用iOS-KVC(二)内部赋值深层次原理iOS-KVC(三)内部取值深层次原理iOS-K...

  • iOS-KVC篇

    一、前言 KVC(Key-value coding)键值编码,是对NSObjcet的扩展,分类名为 : NSKey...

  • iOS-KVO浅谈

    上一篇:iOS-KVC浅谈 前言:KVO 作为 KVC 的同袍兄弟,功能更强大,聊聊 KVO。 一、KVO 简介 ...

网友评论

      本文标题:iOS-KVC篇

      本文链接:https://www.haomeiwen.com/subject/jxcgyltx.html