iOS底层系列26 -- KVC

2021-01-27  本文已影响0人  YanZi_33

KVC定义

KVC的常见API

在Xcode中直接搜索NSKeyValueCoding,看到NSKeyValueCoding是在Foundation框架中以给目标类添加category的形式实现的,主要目标类为NSObject对象类和存储数据的容器类;

Snip20210127_74.png
- (nullable id)valueForKey:(NSString *)key;
- (void)setValue:(nullable id)value forKey:(NSString *)key;
- (nullable id)valueForKeyPath:(NSString *)keyPath;
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;

KVC底层实现原理

1. NSObject类 --> setter方法赋值的底层实现
Snip20210127_76.png
@interface YYPerson : NSObject
{
    @public
    //sex 0-男 / 1-女
    //定义四个实例变量
    //按照顺序:_key,_isKey,key,isKey查找实例变量
    NSString *_sex;
    NSString *_isSex;
    NSString *sex;
    NSString *isSex;
}
@end
@implementation YYPerson

//按照顺序:setKey,_setKey,setIsKey查找set方法
- (void)setSex:(NSString *)value{
    NSLog(@"%s - %@", __func__, value);
}

- (void)_setSex:(NSString *)value{
    NSLog(@"%s - %@", __func__, value);
}

- (void)setIsSex:(NSString *)value{
    NSLog(@"%s - %@", __func__, value);
}

+ (BOOL)accessInstanceVariablesDirectly{
    return YES;
}

- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
    NSLog(@"设置出现异常!!!");
}

@end
NSObject类 --> getter方法取值的底层实现
Snip20210127_77.png
@implementation YYPerson

//按照顺序getKey,key,isKey,_key查找get方法
- (NSString *)getSex{
    return self->sex;
}

- (NSString *)sex{
    return self->sex;
}

- (NSString *)isSex{
    return self->isSex;
}

- (NSString *)_sex{
    return self->_sex;
}

+ (BOOL)accessInstanceVariablesDirectly{
    return NO;
}

- (id)valueForUndefinedKey:(NSString *)key{
    NSLog(@"取值出现异常!!!");
    return nil;
}

面试题一:KVC设置属性能否触发KVO监听回调

- (void)viewDidLoad {
    [super viewDidLoad];

    self.person1 = [[YYPerson alloc]init];
    self.person1.name = @"a";

    [self.person1 addObserver:self forKeyPath:@"name" options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    NSLog(@" change = %@",change);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [self.person1 setValue:@"aaa" forKey:@"name"];
}
Snip20210625_18.png
上一篇 下一篇

猜你喜欢

热点阅读