美文网首页
iOS KVO(键值观察)

iOS KVO(键值观察)

作者: WGLMM | 来源:发表于2020-05-27 10:29 被阅读0次

    KVO(键值观察)

    键值观察是 Objective-C 语言的动态语言特性,在运行时通过 KVO,允许一个对象观察另一个对象的属性,当变化发生时,观察者会得到通知。

    1.注册观察者的方法

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

    2.被监听值的修改执行的方法

    //当key路径对应的属性值发生改变时,监听器就会回调自身的监听方法,如下
    -(void)observeValueForKeyPath:(NSString *)keyPath
                         ofObject:(id)object
                           change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                          context:(void *)context
    

    3.移除监听(这个要写,而且移除之前要判断之前的监听是否还存在,防止重复移除导致崩溃。而且谁注册,谁释放)

    - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(nullable void *)context API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0));
    - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
    

    例如我想关注UIButton的title的变化。

    注册观察者

    [self.timeButton addObserver:self forKeyPath:@"titleLabel.text" options:NSKeyValueObservingOptionNew context:nil];
    

    观察值变化

    -(void)observeValueForKeyPath:(NSString *)keyPath
                         ofObject:(id)object
                           change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                          context:(void *)context
    {
        if ([keyPath isEqualToString:@"titleLabel.text"]) {
            NSLog(@"titleLabel.text = %@",self.timeButton.titleLabel.text);
         }
    }
    

    移除观察者

    //这是我自己一个判断键值观察还存在的
    if ([Tool isObj:self.timeButton hasObserverKey:@"titleLabel.text"]) {
    //移除观察者
        [self.timeButton removeObserver:self forKeyPath:@"titleLabel.text"];
        }
    

    上面基本上就可以实现基本的kvo功能了!!!

    拓展:

    1.属性值变化是系统会调用下面这两个方法:

    - (void)willChangeValueForKey:(NSString *)key
    - (void)didChangeValueForKey:(NSString *)key
    
    options几种值的模式
    // 属性变化的类型,是一个NSNumber对象,包含NSKeyValueChange枚举相关的值
    NSString *const NSKeyValueChangeKindKey;
    
    // 属性的新值。当NSKeyValueChangeKindKey是 NSKeyValueChangeSetting,
    // 且添加观察的方法设置了NSKeyValueObservingOptionNew时,我们能获取到属性的新值。
    // 如果NSKeyValueChangeKindKey是NSKeyValueChangeInsertion或者NSKeyValueChangeReplacement,
    // 且指定了NSKeyValueObservingOptionNew时,则我们能获取到一个NSArray对象,包含被插入的对象或
    // 用于替换其它对象的对象。
    NSString *const NSKeyValueChangeNewKey;
    
    // 属性的旧值。当NSKeyValueChangeKindKey是 NSKeyValueChangeSetting,
    // 且添加观察的方法设置了NSKeyValueObservingOptionOld时,我们能获取到属性的旧值。
    // 如果NSKeyValueChangeKindKey是NSKeyValueChangeRemoval或者NSKeyValueChangeReplacement,
    // 且指定了NSKeyValueObservingOptionOld时,则我们能获取到一个NSArray对象,包含被移除的对象或
    // 被替换的对象。
    NSString *const NSKeyValueChangeOldKey;
    
    // 如果NSKeyValueChangeKindKey的值是NSKeyValueChangeInsertion、NSKeyValueChangeRemoval
    // 或者NSKeyValueChangeReplacement,则这个key对应的值是一个NSIndexSet对象,
    // 包含了被插入、移除或替换的对象的索引
    NSString *const NSKeyValueChangeIndexesKey;
    
    // 当指定了NSKeyValueObservingOptionPrior选项时,在属性被修改的通知发送前,
    // 会先发送一条通知给观察者。我们可以使用NSKeyValueChangeNotificationIsPriorKey
    // 来获取到通知是否是预先发送的,如果是,获取到的值总是@(YES)
    NSString *const NSKeyValueChangeNotificationIsPriorKey;
    //其中,NSKeyValueChangeKindKey的值取自于NSKeyValueChange,它的值是由以下枚举定义的:
    
    enum {
    
        // 设置一个新值。被监听的属性可以是一个对象,也可以是一对一关系的属性或一对多关系的属性。
        NSKeyValueChangeSetting = 1,
    
        // 表示一个对象被插入到一对多关系的属性。
        NSKeyValueChangeInsertion = 2,
    
        // 表示一个对象被从一对多关系的属性中移除。
        NSKeyValueChangeRemoval = 3,
    
        // 表示一个对象在一对多的关系的属性中被替换
        NSKeyValueChangeReplacement = 4
    };
    typedef NSUInteger NSKeyValueChange;
    

    相关文章

      网友评论

          本文标题:iOS KVO(键值观察)

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