KVO -- 键值监听

1、KVO简单介绍

KVO(Key Value Observing)键值监听,属于苹果官方API。

作用:iOS开发中通常将代码分为数据模型和试图控件,数据模型维护程序的状态数据,试图控件将数据模型中的数据展示出来。而KVO能监听当数据模型发生改变时,及时通知试图控件动态将改变的数据显示出来。
注意:只有通过setter方法改变的属性值,才能被KVO监听到,才能触发observeValueForKeyPath:ofObject:change:context:回调方法

KVO的使用:
1.注册需要观察的对象的属性addObserver:forKeyPath:options:context:
2.实现observeValueForKeyPath:ofObject:change:context:方法,这个方法当观察的属性变化时会自动调用
3.取消注册观察removeObserver:forKeyPath:context:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.stu = [[Student alloc] init];

    // 添加观察者
    // observer:观察者  keyPath:想要监听的属性名  options:枚举 回调时可以获取改变前后的值  content:上下文
    [self.stu addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}

// 属性发生改变时的回调
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    // keyPath:属性名  change:改变前后的属性值 content:上下文
    NSLog(@"%@", change[@"new"]);
}

// 释放观察者
- (void)dealloc
{
    [self.stu removeObserver:self forKeyPath:@"age"];
}

2、KVO底层实现(记录自小马哥视频)

当KVO被触发时
1>首先系统会自动创建NSKVONotifying_Student类(这里以Student为例), NSKVONotifying_Student是Student的子类
2>修改当前对象(student)的isa指针,指向NSKVONotifying_Student
3>只要调用对象的setter方法,就会调用NSKVONotifying_Student的setter方法
4>重写NSKVONotifying_Student的setter方法:[super set:],通知观察者对象的属性值发生改变

下面我们来自己实现KVO,以便更好的理解KVO的底层实现过程。
1>系统KVO是基于NSObject,所以我们可以创建一个NSObject的分类NSObject+KVO
NSObject+KVO.h文件

#import <Foundation/Foundation.h>

@interface NSObject (KVO)

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

@end

NSObject+KVO.m文件

#import "NSObject+KVO.h"
#import <objc/runtime.h>
#import "ZKVONotifying_Student.h"

@implementation NSObject (KVO)

- (void)zhaoName_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
{
    // 修改isa指针 本质是改变当前对象的类名
    object_setClass(self, [ZKVONotifying_Student class]);

    // 保存观察者 即动态添加属性
    // object:给哪个对象添加属性  key:属性名  value:属性值  policy:关联策略
    objc_setAssociatedObject(self, @"observer", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

2>重写子类NSKVONotifying_Student的setter方法,通知观察者
NSKVONotifying_Student.m文件

#import "ZKVONotifying_Student.h"
#import <objc/runtime.h>

@implementation ZKVONotifying_Student

- (void)setAge:(NSUInteger)age
{
    [super setAge:age];

    // 获取保存的观察者
    id observer = objc_getAssociatedObject(self, @"observer");
    // 通知
    // 注意这里change传nil,则在回调时change为空
    [observer observeValueForKeyPath:@"age" ofObject:self change:nil context:nil];
}

@end

这样调用我们自己实现的KVO也能实现属性改变的监听

[self.stu zhaoName_addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值