如何手动触发一个 value 的 KVO?

作者: iOS猿_员 | 来源:发表于2019-01-29 20:59 被阅读73次

原文:iOS面试题大全

KVC,即是指 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性。KVO 就是基于 KVC 实现的关键技术之一。

键值观察通知依赖于 NSObject 的两个方法: willChangeValueForKey:didChangevlueForKey:。在一个被观察属性发生改变之前,willChangeValueForKey: 一定会被调用,这就会记录旧的值。而当改变发生后,observeValueForKey:ofObject:change:context:didChangeValueForKey:也会被调用。如果可以手动实现这些调用,就可以实现“手动触发”了。

    @property (nonatomic, strong) NSDate *now;
    - (void)viewDidLoad {
       [super viewDidLoad];
       _now = [NSDate date];
       [self addObserver:self forKeyPath:@"now" options:NSKeyValueObservingOptionNew context:nil];
       NSLog(@"1");
       [self willChangeValueForKey:@"now"]; // 手动触发 self.now 的 KVO,必写。
       NSLog(@"2");
       [self didChangeValueForKey:@"now"]; // 手动触发 self.now 的 KVO,必写。
       NSLog(@"4");
    }
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
       NSLog(@"3");
    }

打印顺序是:1 2 3 4。从这里看顺序似乎是 wilChangeValueForKey:observeValueForKeyPath:ofObject:change:context:didChangeValueForKey:。其实,实际情况是:wilChangeValueForKey:先调用,接着是调用 didChangeValueForKey:,在 didChangeValueForKey: 内部调用了 observeValueForKeyPath:ofObject:change:context:。你可以注释掉[self didChangeValueForKey:@"now"];试试。

但是平时我们一般不会这么干,我们都是等系统去“自动触发”。“自动触发”的实现原理:

比如调用 setNow: 时,系统还会以某种方式在中间插入 wilChangeValueForKey:didChangeValueForKey:observeValueForKeyPath:ofObject:change:context:的调用。

大致表现如下:

    - (void)setNow:(NSDate *)aDate {
       [self willChangeValueForKey:@"now"];
       [super setValue:aDate forKey:@"now"];
       [self didChangeValueForKey:@"now"];
    }

Apple 使用了 isa 混写(isa-swizzling)来实现 KVO,这种继承和方法注入是在运行时而不是编译时实现的。这就是正确命名如此重要的原因。只有在使用 KVC 命名约定时,KVO 才能做到这一点。KVO 在实现中通过 isa 混写(isa-swizzling)把这个对象的 isa 指针(isa 指针告诉 Runtime 系统这个对象的类是什么)指向这个新创建的子类,对象就神奇的变成了新创建的子类的实例。Apple 还重写、覆盖了 -class 方法并返回原来的类,企图欺骗我们:这个类没有变,就是原本那个类。

相关文章

  • iOS KVO的手动实现过程

    如何手动触发一个value的KVO 手动实现 willChangeValueForKey 和 didChangeV...

  • iOS面试题-OC

    1. 如何手动触发一个value的KVO NSObject 有 willChangeValueForKey: 和...

  • IOS问题与解答

    对KVO原理的理解: 问:如何手动触发一个value的KVO 答:主动调用: willChangeValueFor...

  • KVO

    iOS用什么方式实现对一个对象的KVO 如何手动触发KVO 直接修改成员变量会触发KVO么? KVO [self....

  • 04. KVO使用,原理,本质

    问题 KVO日常使用 KVO原理(KVO本质是什么) 如何手动触发KVO 直接修改成员变量会触发KVO吗 KVO图...

  • 如何手动触发一个value的KVO?

    所谓的“手动触发”是区别于“自动触发”:自动触发是指类似这种场景:在注册 KVO 之前设置一个初始值,注册之后,设...

  • 如何手动触发一个value的KVO

    所谓的“手动触发”是区别于“自动触发”: 想知道如何手动触发,必须知道自动触发KVO的原理: 转载自《猿圈》 那么...

  • 如何手动触发一个 value 的 KVO ?

    自动触发场景:在注册 KVO 之前设置一个初始值,注册之后,设置一个不一样的值,这样就可以触发了。 手动触发:

  • 如何手动触发一个 value 的 KVO?

    原文:iOS面试题大全 KVC,即是指 NSKeyValueCoding,一个非正式的 Protocol,提供一种...

  • 深入理解KVO

    iOS | KVO | Objective-C KVO的本质是什么,如何手动触发KVO? 1.什么是KVO KVO...

网友评论

    本文标题:如何手动触发一个 value 的 KVO?

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