成员变量没有手动添加setter方法,使用KVC赋值为什么会触发KVO?

来源:4-10 KVC相关面试问题

慕尼黑6324595

2019-03-20

#import <Foundation/Foundation.h>

@interface MObject : NSObject
{
    int _value;
}
@end
@implementation MObject
- (id)init
{
    self = [super init];
    if (self) {
        _value = 0;
    }
    return self;
}
@end


@interface MObserver : NSObject
@end
@implementation MObserver

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    if ([object isKindOfClass:[MObject class]] &&
        [keyPath isEqualToString:@"value"]) {
        // 获取value的新值
        NSNumber *valueNum = [change valueForKey:NSKeyValueChangeNewKey];
        NSLog(@"value is %@", valueNum);
    }
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        MObject *obj = [[MObject alloc] init];
        MObserver *observer = [[MObserver alloc] init];
        //调用kvo方法监听obj的value属性的变化
        [obj addObserver:observer forKeyPath:@"value" options:NSKeyValueObservingOptionNew context:NULL];
        [obj setValue:@2 forKey:@"value"];
    }
    return 0;
}

这样调用KVC为什么能触发KVO?

写回答

3回答

杰西大叔

2020-03-30

验证了一下,对于没有setter方法的合法属性,kvc会自己给属性赋值,赋值的时候调用的是 _NSSetValueAndNotifyForKeyInIvar 看名字不难理解,边赋值边通知值的变化,方法里面调用了willChangeValueForKey 和 didChangeValueForKey 这样kvo就接上了。

0
1
卷王Charles
请教下,这个是怎么验证的?
2021-10-08
共1条回复

闲逛的蚂蚁

2019-08-17

我也有此疑问,按照setValue:ForKey:方法内部的处理流程,在判断没有setter方法之后,应该是直接会通过实例变量进行赋值,那通过实例变量直接赋值应该不会触发KVO的回调才对啊,求解答~

0
2
慕慕6239994
[obj addObserver:observer forKeyPath:@"value" options:NSKeyValueObservingOptionNew context:NULL]; 这个给value添加监听,其实内部是有给value重写setValue方法的。 那么KVC [obj setValue:@2 forKey:@"value"]的的实现原理刚好就是调用了setValue方法。 所以就触发了KVO。 换句话说就是:你虽然没有手动给她添加setter方法,但是KVO的实现底层给他添加了 所以能很好的触发KVO。
2019-09-11
共2条回复

于海

2019-03-22

看课程中关于kvc的原理介绍

0
0

资深大牛带你深度剖析ios高级面试

从BAT/TMD名企真题入手,结合源码及应用,构建完整iOS知识体系

1749 学习 · 600 问题

查看课程