5.KVC

1.KVC

 - (void)setValue:(nullable id)value forKey:(NSString *)key;
 - (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
 - (nullable id)valueForKey:(NSString *)key;
 - (nullable id)valueForKeyPath:(NSString *)keyPath;
  • 可以访问私有的成员变量和属性

2. setValue:forKey: 的原理

在这里插入图片描述

  • KVC的赋值过程 :
  1. 先找到相关方法
    set, _set : 按顺序,如果前面的方法都没有找到,执行后续方法
  2. +(BOOL)accessInstanceVariableDirectly:
    判断是否可以直接赋值,默认返回值时YES
    如果返回值是NO : 直接抛出一个异常 setValue:forUndefinedKey:
    如果返回值是YES : 继续查找成员变量
  3. 查找成员变量
    _Key ,_isKey ,Key ,isKey ,找到这些成员变量,然后赋值.
  4. 方法或者成员变量都找不到,默认抛出异常
.h
    NSString *_name;//1
    NSString *_isName;//2
    NSString *name;//3
    NSString *isName;//4
.m
[p setValue:@"yuanhao" forKey:@"name"];;
    NSLog(@"name = %@",p->_name);//1.1  _key
    NSLog(@"_name = %@",p->_isName);//2.1 _iskey
    NSLog(@"isName = %@",p->name);//3.1 key
    NSLog(@"_isName = %@",p->isName);//4.1 iskey
    
    /*
    如果没有都没有注释,1.1有值
    注释了1 , 2.1打印值,其它都为null
    注释了1,2 , 3.1打印值,其它为null
    ...
    给key name赋值,按步骤4的顺序,先给_name赋值,如果没有_name的变量,再给_isName赋值.....
    */


3. valueForKey: 的原理

在这里插入图片描述

  • 取值过程
  1. 先找到相关方法
    get,,is,<_Key>
  2. 如果没有找到相关方法
    +(BOOL)accessInstanceVariableDirctly:
    如果返回值是NO , 直接抛出一个异常,valueForUndefinedKey:
    如果返回值是YES
  3. 继续查找成员变量
    _key ,_isKey ,key ,isKey ,找到这些成员变量直接取值
  4. 方法或者成员变量都不存在,抛出异常

4. KVC进阶用法

1. KVC异常处理,正确性验证
  • 可以复写这些方法来捕获错误
-(void)setNilValueForKey:(NSString *)key{}
-(void)setValue:(id)value forUndefinedKey:(NSString *)key{}
-(id)valueForUndefinedKey:(NSString *)key

2.KVC与字典
- setValueForKeysWithDictionary: //字典转模型

 [self dictionaryWithValuesForKeys:<#(nonnull NSArray<NSString *> *)#>] //
 - (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys; //模型转字典

3.KVC消息传递

给数组的每个成员变量发送消息

- (void)arrayKVCTest{
    NSArray *arr =@[@"monday",@"yuanhao",@"fengfeng"];
    NSArray *lengthArr = [arr valueForKey:@"length"];
    NSLog(@"%@",lengthArr);
    (
    6,
    7,
    8
)

4. KVC容器操作
  1. 聚合操作符 @avg,@count,@max,@min,@sum
  2. 数组操作符
  3. 嵌套集合(array&set)操作
  • 聚合操作

p1.height = 1.65
p2.height = 1.55
arr addObject:p
[arr valueForKey:@"height"]; //获取所有的成员的高度

//平均身高
[[arr valueForKey:@"@avg.height"] floatValue]
  • 数组操作符
[arr valueForKey:@"@distindtUnionOfObjects.height"] //去重
  • 嵌套集合(array&set)操作
类似2.

5.面试题

1.通过KVC修改属性会触发KVO么?

会触发KVO

self->_age = @"3333"; //直接给成员变量赋值不会触发KVO
    _age = @"123"; // 直接修改成员变量不会触发KVO
    [self setValue:@"1234" forKey:@"_age"];//不会触发KVO age是属性 修改属性的成员变量不会触发KVO
    [self setValue:@"1234" forKey:@"age"];//会触发KVO 直接修改属性会触发KVO
    _height = 100; // 不会触发KVO 直接修改成员变量不会触发KVO
/*
     [self addObserver:self forKeyPath:@"_height" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:@"self-_hright"];
     如果直接观察成员变量,KVC能够触发
     */
    [self setValue:@123 forKey:@"_height"];//使用KVC修改成员变量会触发KVO
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值