键值监听-KVO

KVO概述

键值观察Key-Value-Observer就是观察者模式。利用一个key来找到某个属性并监听其值的改变。KVO建立在 KVC 之上,它能够观察一个对象的 KVC key path 值的变化。
KVO提供一种机制,指定一个被观察的对象(A类),当对象某个属性(A类中的属性name)发生更改时,对象会获得通知,并作出相应处理。且不需要给A类添加任何额外代码,我称之为偷窥

特点

观察者观察的是属性,只有遵循KVO变更属性值的方式才会执行KVO的回调方法,例如是否执行了setter方法。如果赋值没有通过setter方法或者KVC,而是直接修改属性对应的成员变量,例如:仅调用_name = @"newName",这时是不会触发KVO机制,更加不会调用回调方法的。所以使用KVO机制的前提是遵循KVO的属性设置方式来变更属性值。

应用

KVO的应用分为三个步骤

1.注册监听者,开始偷窥
2.在回调方法中处理属性发生的变化
3.移除监听者
注册监听者

KVO机制由NSKeyValueObserving协议提供支持,NSObject遵守了该协议,该协议包含了如下常用方法用于注册监听器

//anObserver:观察者
//keyPath:要观察的属性
//options:给你观察键值变化的选择
//context:方便传输你需要的数据
- (void)addObserver:(NSObject *)anObserver
        forKeyPath:(NSString *)keyPath
           options:(NSKeyValueObservingOptions)options
           context:(void *)context
监听方法(回调方法)

当属性变化时,激发监听方法

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context

由此可见,作为监听器的组件需要重写该方法

移除监听者
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath

小小小Demo

新建工程先
新建文件父类NSObject
KVO.h

@interface KVO : NSObject
@property (nonatomic , assign) int num;
@end

ViewController.h中

@interface ViewController : UIViewController
@property (nonatomic , strong) UILabel* label;
@property (nonatomic , strong) UIButton* button;
@property (nonatomic , strong) KVO* myKvo;
@end

ViewController.m中

//
//  ViewController.m
//  KVO
//
//  Created by 王旭 on 2020/8/13.
//  Copyright © 2020 王旭. All rights reserved.
//

#import "ViewController.h"
#import "KVO.h"
//#import <objc/runtime.h>
@interface ViewController ()
@property (nonatomic , strong) KVO* myKvo;
 /*1.注册对象myKvo为被观察者: option中, NSKeyValueObservingOptionOld 以字典的形式提供 “初始对象数据”; NSKeyValueObservingOptionNew 以字典的形式提供 “更新后新的数据”; */
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor yellowColor];
    
    _label = [[UILabel alloc] init];
    _label.frame = CGRectMake(200, 200, 150, 30);
    _label.font = [UIFont systemFontOfSize:20];
    _label.text = 0;
    
    
    _button = [[UIButton alloc] init];
    _button.frame = CGRectMake(170, 500, 100, 40);
    _button.backgroundColor = [UIColor grayColor];
    
    [_button addTarget:self action:@selector(changeNum) forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:_label];
    [self.view addSubview:_button];
    
    self.myKvo = [KVO new];
    [self.myKvo addObserver:self forKeyPath:@"num" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:@"123"];
//    NSLog(@"%s",object_getClassName(self.myKvo));
    /* 2.只要object的keyPath属性发生变化,就会调用此回调方法,进行相应的处理:UI更新:*/
}
- (void) changeNum
{
    //KVC方法setValue
   // [self.myKvo setValue:@"20" forKey:@"num"];
    //set方法
   //   [self.myKvo setNum:20];
    //点语法
    self.myKvo.num = 20;
}
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    

    // 判断是否为self.myKVO的属性“num”:
    if(context ==@"123" && object == self.myKvo)
    {
     // 响应变化处理:UI更新(label文本改变)
        NSLog(@"old num:%@ new num:%@",[change valueForKey:@"old"], [change valueForKey:@"new"]);
    }
}
- (void) dealloc
{
    [_myKvo removeObserver:self forKeyPath:@"num"];
}
@end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

waxuuuu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值