iOS - KVC中 forKey 和 forKeyPath区别

KVC全称是Key-Value Code,俗称键值对,可以通过一个key来访问某个属性。

  • 常见的API有
    设置属性值:setValue:<#(nullable id)#> forKey:<#(nonnull NSString *)#>setValue:<#(nullable id)#> forKeyPath:<#(nonnull NSString *)#>
    获取属性值:valueForKey:<#(nonnull NSString *)#>valueForKeyPath:<#(nonnull NSString *)#>
1. forKey 和 forKeyPath 设置值的区别

// forKey用法
    Person *p = [[Person alloc]init];
    [p setValue:@10 forKey:@"age"];
    NSLog(@"-- %ld",p.age); //  -- 10

    // forKeyPath用法
    Person *p = [[Person alloc]init];
    //[p setValue:@10 forKey:@"age"];
    [p setValue:@20 forKeyPath:@"age"];
    NSLog(@"-- %ld",p.age); //-- 20

单从这两个基础设值来看,用法一样,没有太大区别,我们来看下差异之处:

比如有这样一个Person类,里面有一个Student类

Person.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface Student : NSObject
@property (nonatomic,assign) NSInteger weight;
@end

@interface Person : NSObject
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, strong) Student *stu;
@end

NS_ASSUME_NONNULL_END

Person.m

@implementation Student

@end

@implementation Person

@end

代码示例:

Person *p = [[Person alloc]init];
    Student *stu = [[Student alloc]init];
    p.stu = stu;
    //[p setValue:@10 forKey:@"age"];
    //[p setValue:@20 forKeyPath:@"age"];
    [p setValue:@30 forKeyPath:@"stu.weight"];
    NSLog(@"-- %ld",p.stu.weight);
2. forKey 和 forKeyPath 取置值的区别

Person *p = [[Person alloc]init];
    p.age = 10;
    NSLog(@"-- %@",[p valueForKey:@"age"]);
    NSLog(@"-- %@",[p valueForKeyPath:@"age"]);

还是单从这两个基础设值来看,用法一样,没有太大区别,我们来看下差异之处:

Person *p = [[Person alloc]init];
    Student *stu = [[Student alloc]init];
    p.stu = stu;
    p.age = 10;
    p.stu.weight = 30;
    NSLog(@"-- %@",[p valueForKey:@"age"]);
    NSLog(@"-- %@",[p valueForKeyPath:@"stu.weight"]);

【小结】

  • keyPath 相当于根据路径去寻找属性,一层一层往下找;
  • key 是直接根据属性名字设置值,如果按路径找会报错

【 拓展 】

setValue / valueForKeyPath 方法也会触发KVO事件,如下图所示:

image.png
setValue:forKey: 赋值的原理
setValue-forKey.jpg

步骤:当我们设置setValue:forKey:时;
① 首先会查找setKey:、_setKey: (按顺序查找);
② 如果有直接调用,如果没有,先查看accessInstanceVariablesDirectly方法;

+ (BOOL)accessInstanceVariablesDirectly{
     return YES;   /// 可以直接访问成员变量
     //return NO;  ///  不可以直接访问成员变量,  
     /// 直接访问会报NSUnkonwKeyException错误  
 }

③ 如果可以访问会按照 _key、_isKey、key、iskey的顺序查找成员变量,找到直接赋值;

image.png
image.png

④ 未找到报错NSUnkonwKeyException错误

image.png
image.png
【 小结 】
所以, setValue:@10 forKey:@"age" 修改age,核心还是应为调用了 willChangeValueForKey:keydidChangeValueForKey:key
valueForKey: 取值的原理
valueForKey.jpg

步骤:当我们设置valueForKey:时;
① kvc取值按照 getKey、key、iskey、_key 顺序查找;

② 存在直接调用,如果没找到,同样会先查看accessInstanceVariablesDirectly方法;

+ (BOOL)accessInstanceVariablesDirectly{
     return YES;   /// 可以直接访问成员变量
     //return NO;  ///  不可以直接访问成员变量,  
     /// 直接访问会报NSUnkonwKeyException错误  
 }

③ 如果可以访问会按照 _key、_isKey、key、iskey的顺序查找成员变量,找到直接赋值;

image.png
image.png

④ 未找到报错NSUnkonwKeyException错误。

image.png

END.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值