iOS Runtime之KVO

2022-06-26  本文已影响0人  谢二九

Runtime系列导读

KVO简介

全称Key-Value Observing,KVO是Object-C中定义的一个通知机制,其定义了一种对象间监控对方状态的改变,并做出反应的机制。对象可以为自己的属性注册观察者,当这个属性的值发生了改变,系统会对这些注册的观察者做出通知。

KVO用法

添加监听

- (void)addObserver:(NSObject *)observer  
         forKeyPath:(NSString *)keyPath  
            options:(NSKeyValueObservingOptions)options  
            context:(void *)context  

监听实现

-(void)observeValueForKeyPath:(NSString *)keyPath
                     ofObject:(id)object
                       change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                      context:(void *)context

KVO实现过程

KVO的实现过程实际上是利用了OC的runtime机制,当一个实例对象添加观察者时,底层根据该实例对象所属的类动态添加了一个类(动态添加的类名就是在原来类的类名前加上NSKVONotifying_前缀),这个类是继承自原来的类的。这里以继承自NSObject的KVOTest类来举例。

@interface KVOTest : NSObject

@property (nonatomic, assign) NSInteger age;


@end

@implementation KVOTest

-(void)didChangeValueForKey:(NSString *)key
{
    [super didChangeValueForKey:key];
    NSLog(@"didChangeValueForKey:%@,%p", key, self);
}

@end
-(void)testKVO2
{
    self.test = [KVOTest new];
    self.test.age = 10;
    NSKeyValueObservingOptions option = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
    [self.test addObserver:self forKeyPath:@"age" options:option context:nil];
    self.test.age = 10;
}
-(void)observeValueForKeyPath:(NSString *)keyPath
                     ofObject:(id)object
                       change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                      context:(void *)context
{
    NSLog(@"%@ - %@" , keyPath, change);
}
2022-06-25 21:58:32.716895+0800 StudyApp[31571:1344036] age - {
    kind = 1;
    new = 10;
    old = 10;
}
2022-06-25 21:58:32.716960+0800 StudyApp[31571:1344036] didChangeValueForKey:age,0x600003f14590

上面实例的底层实现过程如下:

KVO答疑

如何手动触发KVO?

直接修改成员变量会触发KVO吗?

对同一个属性N次注册,修改一次该属性,observeValueForKeyPath会调用几次

N次。

对同一个属性一次注册,多次removeObserver,会发生什么

crash,提示**'Cannot remove an observer <ViewController 0x7fa3fd708c60> for the key path "age" from <KVOTest 0x6000018e8790> because it is not registered as an observer.'**

上一篇下一篇

猜你喜欢

热点阅读