首页 > 代码库 > iOS核心笔记—KVO机制

iOS核心笔记—KVO机制

1、KVO

  • KVO简介:Key Value Observing,通过Key键观察对象的对应Key键的属性值Value是否发生改变。

  • KVO的作用: 当前对象想监听另一个对象的某个属性是否发生变化。

  • KVO使用步骤:①给对象的某个属性添加监听器;②监听器实现监听方法;③对象销毁前一定要移除监听器。

  • 当前对象监听另一个对象的某个属性:

    [person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    
    • 格式: [被监听对象 addObserver:监听者 forKeyPath:属性名 options: context:]

    • 被监听者告诉监听器你要监听我的哪个属性。

  • NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld 的作用,当当前对象实现监听方法后,监听方法中的change字典中能够获取监听的另一个对象属性改变前后的值。

  • 当前对象实现- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context方法

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
        NSLog(@"%@对象的%@属性发生变化", object, keyPath);
        NSLog(@"%@", change);
    }
    
  • 在监听方法中,可以根据相应的key去获取change字典中的对应的值。 

  • 当前对象监听被监听对象的属性必须在前,另一个对象的属性变化必须在后;

  • 在被监听对象销毁前一定要移除监听器;

  • 完整的KVO监听:

  - (void)viewDidLoad {
    [super viewDidLoad];

    // 1. 创建Person对象
    HFPerson *p = [[HFPerson alloc] init];
    // 2. 注册监听
    [p addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    // 3. 改变对象属性
    p.name = @"卡哇伊";
    // 4. 移除监听
    [p removeObserver:self forKeyPath:@"name"];
}

/**
 监听器实现的监听方法

 @param keyPath 哪个被监听器监听的属性
 @param object  哪个对象被监听器监听
 @param change  保存对象属性值变化前后的字典
 @param context 对象注册监听器时传入的数据(一般用于对象之间进行通信)
 */
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    NSLog(@"%@", change);
}
  • KVO示例:

    
    // cc监听了aa的name属性的改变
    [aa addObserver:cc forKeyPath:@"name" options: NSKeyValueObservingOptionOld context:nil];
    
    // cc得实现监听方法
    
    /**
    * 当监听到object的keyPath属性发生了改变
    */
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
    NSLog(@"监听到%@对象的%@属性发生了改变, %@", object, keyPath, change);
    }
    

2、KVC\KVO使用场景:

  • KVC(Key Value Coding)常见作用:给模型属性赋值;

  • KVO(Key Value Observing)常用作用:监听模型属性值的改变。

【BUG汇总】

  • BUG-1:被监听对象已经销毁,但是没有移除监听; 

  • 解决方案:在被监听对象销毁前移除监听,可以尝试在被监听对象的dealloc方法中移除监听器;但是,可能需要将监听器作为属性保存至被监听对象中、或者使用代理、block。 

  • 注意事项:被监听对象移除监听器时,监听器和被监听的属性必须和注册监听时一模一样;否则,程序将会崩溃。 

 

iOS核心笔记—KVO机制