• 【iOS开发- KVO(键值监听)】


    KVO是什么

     在iOS开发的过程中,iOS应用通常会把应用程序组建分开成数据模型组件和视图组件
     其中数据模型组件负责维护应用程序的状态数据
     而视图组件则负责显示数据模型组件内部的状态数据
    
    • 1
    • 2
    • 3

    KVO的来由

        对于上面介绍的设计结构,如果程序存在的需求是:
        在数据模型组件的状态数据发生改变的时候,
        希望视图组件能动态的更新自己,及时的显示数据模型更新后的数据。
    
    • 1
    • 2
    • 3
    • 为此,iOS提供了利用KVO(Key Value Observing,键值监听)机制,NSObject的子类(所有的Oc类都是NSObject的子类)都可以使用该协议中的方法
    • KVO机制由NSKeyValueObserving协议提供支持 ,该协议包含了一下常用方法用于住注册监听器
      • addObserver:forlKeyPath:options:context::注册-个监听器用于监听指定的key 路径。
      • removeObserver:forkeyPath::为key路径删除指定的监听器
      • removeObserver:forKeyPathicontext:为key 路径删除指定的监听器。只是多了—个 context
        参数。
    • 对于上面的需求,很容易想到可以让视区组件来监听数据模型组件的改变,当数据模型组件的key 路径对应的属性值发生改变时,作为监听器的视图组件将会被激发,激发时就会回调监听器自身的监听方法。该监听方法如下:
    observeValueForKeyPath:ofObject:change:context
    
    • 1

    由此可见,作为监听器的视图组件需要重写observeValue ForkeyPath:ofObject:change: context方法,重写该方法时就可以得到最新改的数据,从而使用最新的数据来更新视图组件的显示

    • 从上面的介绍不难看出,KVO 编程的生骤非常简单
      • ①为被监听对象(通常是数据模型组件》注朋监听器
      • ②重写监听器的 observe ValueForKeyPath:ofObject:change:context:方法

    KVO实例

    • 和以前一样,创建一个Dog类
    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface Dog : NSObject
    @property (nonatomic, assign) int high;
    @end
    
    NS_ASSUME_NONNULL_END
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 我们在视图里面实现一下改变,然后打印改变
    • ViewController.m
    #import <UIKit/UIKit.h>
    #import "Dog.h"
    
    @interface ViewController : UIViewController
    @property (nonatomic, strong) UILabel* label;
    @property (nonatomic, strong) UIButton* button;
    @property (nonatomic, strong) Dog* lyt;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • ViewContrller.h
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        self.view.backgroundColor = [UIColor whiteColor];
        _label = [[UILabel alloc] init];
        _label.frame = CGRectMake(100, 300, 200, 50);
        _label.font = [UIFont systemFontOfSize:20];
        [self.view addSubview:_label];
        
        // 初始化点击button
        _button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [_button setTitle:@"长高" forState:UIControlStateNormal];
        [_button addTarget:self action:@selector(pressButton:) forControlEvents:UIControlEventTouchUpInside];
        _button.frame = CGRectMake(15, 400, 100, 40);
        [self.view addSubview:_button];
     // 设置监听   
        _lyt = [[Dog alloc] init];
        [_lyt addObserver:self forKeyPath:@"high" options:NSKeyValueObservingOptionNew |NSKeyValueObservingOptionNew context:nil];
        
        
    }
    // 点击button触发监听
    - (void)pressButton: (UIButton*)button {
        static int high = 0;
        _lyt.high = high++;
    }
    
    // 监听方法
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
        NSString* str = [NSString stringWithFormat:@"我的身高%d", _lyt.high];
        _label.text = str;
        NSLog(@" new high %@", [change valueForKey:@"new"]);
    }
    // 移除监听
    - (void)dealloc {
        [_lyt removeObserver:self forKeyPath:@"high"];
    }
    
    
    @end
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    监听效果展示

    • 点击一下button 我们设置的监听事件就触发一次
      请添加图片描述

    • 记得最后加上取消监听函数(在不使用的时候移除监听)

    // 移除监听
    - (void)dealloc {
        [_lyt removeObserver:self forKeyPath:@"high"];
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    Linux Shell脚本
    centos常用命令
    云原生之史上最全K8S环境搭建(强烈建议收藏)
    揭秘”智能定投“
    工作中一些计算日期的要求
    1.java环境搭建与eclipse安装和配置
    【三十】springboot项目上高并发解决示例
    Gitlab使用
    闪击笔试题
    【Linux】第十五章 多线程(线程池)
  • 原文地址:https://blog.csdn.net/weixin_61639290/article/details/126116370