详解KVO底层实现

KVO 正确使用姿势进阶及底层实现 你要知道的KVC、KVO、Delegate、Notification都在这里 转载请注明出处 http://blog.youkuaiyun.com/u014205968/article/details/78224820 本系列文章主要通过讲解KVC、KVO、Delegate、Notification的使用方法,来探讨KVO、Delegate、Notification的区别以及相关使用场景,本系列文章将分一... 阅读详情

前言

KVO: Key-Value-Observer,它来源于观察者模式, 其基本思想(copy于某度)是
一个目标对象管理所有依赖于它的观察者对象,并在它自身的状态改变时主动通知观察者对象。这个主动通知通常是通过调用各观察者对象所提供的接口方法来实现的。观察者模式较完美地将目标对象与观察者对象解耦。

本质

当某个类的实例对象的key第一次被观察时,系统就会在运行期动态地创建该类的一个派生类NSKVONotifying_类名,在这个派生类中重写该类中被观察的属性的 setter 方法。

一步一步验证

  • ①. KVO的本质就是监听对象的属性进行赋值的时候有没有调用setter方法. 如果有调用setter方法, 就会接收到属性变更的通知, 反之则没有.

    我们新建一个类Person, 定义一个属性name, 并自己实现它的setter方法

@property(nonatomic, copy) NSString *name;
- (void)setName:(NSString *)name
{
    _name = [name copy];

    NSLog(@"%s", __FUNCTION__);
}

随后, 我们在ViewController中添加Person的实例对象的属性name的属性监听, 暨添加KVO, 并实现处理变更通知方法 observeValueForKeyPath

 self.p = [[Person alloc] init];
 [self.p addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"%@, %@", keyPath, self.p.name);
}

此时, 我们在点击屏幕的时候, 给实例对象p的name进行赋值

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    static int i = 0;
    self.p.name = [NSString stringWithFormat:@"name->%d", i++];
}

运行程序, 点击两次屏幕, 我们可以可以观察到打印如下

-[Person setName:]
name, name->0
 -[Person setName:]
name, name->1

我们再进行一次反证, 我们不使用setter方法对name进行赋值, 看是否属性的值改变会被监听
我们将Person.h修改如下

@interface Person : NSObject
{
@public NSString *_name;
}
@property(nonatomic, copy) NSString *name;
@end

此时, @property只会帮我们生成getter方法(setter已经被我们自己实现了的), 不会生产_name成员变量

我们修改点击屏幕的代码如下

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    static int i = 0;
    self.p->_name = [NSString stringWithFormat:@"name->%d", i++];
}

此时我们运行程序会发现, 不管怎么点击屏幕, 控制台都不会有任何打印.

结论:
 KVO的本质就是监听对象的属性进行赋值的时候有没有调用`setter`方法

② 当某个类的实例对象的key第一次被观察时,系统就会在运行期动态地创建该类的一个派生类NSKVONotifying_类名,在这个派生类中重写该类中被观察的属性的 setter 方法

如果我们要重写方法, 一般都会调用[super 方法名], 那么系统是怎么做到重写属性的setter方法, 且通知观察者Observer的呢? 下面我们一步一步来进行分析:

这里写图片描述

如图所示, 我们有断点A和B, 此时我们运行程序, 程序在停留在断点A处, 我们观察isa指针

这里写图片描述

此时,isa指针指向Person类
我们跳过这个断点, continue, 并点击屏幕, 此时程序停留到了断点B, 此时我们再次观察isa

这里写图片描述

此时isa指针被系统动态的指向了派生类NSKVONotifying_Person. 由此, 结论被证.


自己实现KVO

由于系统是自动实现的派生类NSKVONotifying_Person, 这儿我们自己手动创建一个派生类ALINKVONotifying_Person, 继承自Person. 同时给NSObject创建一个分类, 让每一个对象都拥有我们自定义的KVO特性.

NSObject+KVO.h

#import <Foundation/Foundation.h>

@interface NSObject (KVO)

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

NSObject+KVO.m

#import "NSObject+KVO.h"
#import "ALINKVONotifying_Person.h"
#import <objc/message.h>

NSString *const ObserverKey = @"ObserverKey";

@implementation NSObject (KVO)

// 仿系统的, 前缀是为了区别系统的
- (void)alin_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context
{
    // 把观察者保存到当前对象
    objc_setAssociatedObject(self, (__bridge const void *)(ObserverKey), observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    // 修改对象isa指针
    object_setClass(self, [ALINKVONotifying_Person class]);
}

@end

ALINKVONotifying_Person.m

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

extern NSString *const ObserverKey;

@implementation ALINKVONotifying_Person
- (void)setName:(NSString *)name
{
    [super setName:name];

    // 获取观察者
    id obsetver = objc_getAssociatedObject(self, ObserverKey);

    [obsetver observeValueForKeyPath:@"name" ofObject:self change:nil context:nil];
}

@end

此时我们调用自己定义的监听方法, 效果和系统的也是一样的

[self.p alin_addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
iOS之深入解析KVO的底层原理 一、KVO 简介 ① 概念 KVO 全称 Key Value Observing,是苹果提供的一套事件通知机制,允许对象监听另一个对象特定属性的改变,并在改变时接收到事件。 由于 KVO 的实现机制,所以对属性才会发生作用,一般继承自 NSObject 的对象都默认支持 KVO。 KVO 和 NSNotificationCenter 都是 iOS 中观察者模式的一种实现,区别在于,相对于被观察者和观察者之间的关系,KVO 是一对一的,而 NSNotificationCenter 是一对多的,KVO 对被监 阅读详情

相关推荐

Delta机器人:运动学正反解分析

Delta机器人:运动学正反解分析 一、Delta机构简介 Delta机构是并联机构中的一种典型机构,起原始结构如图1所示。Delta机构由R.Clavel 博士在 1985年发明,是现在并联机器人中使用最多的一种,具备了并联机构所特有的优点,负载能力强、效率高、末端执行器精度高、运动惯性小,可以高速稳定运动等。因此在机器人领域获得了越来越广泛的应用。以实现高速、精准、高效的运动。           &n

花洛兮灬 3万+

iOS KVO底层实现原理

一:KVO系统实现 首先分析一下系统的实现 #import &lt;Foundation/Foundation.h&gt; @interface Person : NSObject @property (copy, nonatomic) NSString *name; @end #import "Person.h" @implementation Person @end #i...

人不风流枉少年 1777

使用moveit控制机械臂

位置设置:`target_pose.position.x = 0.12`, `target_pose.position.y = 0.41`, 和 `target_pose.position.z = 0.44` 分别设置了机械臂末端执行器的X, Y, 和 Z坐标。设定目标位置:`group.set_pose_target(target_pose)` 这一命令将之前定义的目标位置和姿态设置为当前机械臂组的目标,为接下来的路径规划做准备。在机械臂控制的过程中,设定精确的目标位置和姿态是实现精确操作的关键步骤。

realman_Rop的博客 3687

【iOS】KVO底层原理

【iOS底层原理】KVO

cheng_lin0201的博客 685

Transformer模型在语义通信中的实战应用:从信源编码到端到端优化

本文深入探讨了Transformer模型在语义通信中的实战应用,从信源编码到端到端优化。文章分析了Transformer凭借其强大的全局依赖建模能力,如何成为实现高效语义提取与传输的理想架构,并提供了构建可端到端训练系统的具体实现思路与评估方法,旨在为下一代智能通信系统提供技术参考。

o9p0q1的博客 689

量子城域网系列(六):从星型到环形,解析QKD网络拓扑的演进与选型

本文深入解析了量子密钥分发网络从星型到环形等主流拓扑结构的演进历程与核心原理。针对量子城域网的实际部署,文章详细对比了星型、总线型和环形拓扑的优缺点,并结合政务云、金融网点等典型应用场景,提供了实战选型指南,帮助读者在物理限制、安全需求与成本效率间找到最佳平衡。

weixin_29197835的博客 111

OC:跟随码哥一起学习KVO

当实例对象 Person 的 age 值发生变化,根据实例对象 isa 指针找到对应的类对象,然后调用对应类对象的方法。:KVO的全称是Key-Value Observing,俗称“键值监听”,可以用于监听某个对象属性值的改变。而对象添加KVO处理,肯定是在实现 setAge: 方法的时候,触发了监听器(Oberser)的监听方法。2.1、查看添加KVO时,类对象与元类对象的变化。3.1、未使用KVO监听的对象。3.2、使用了KVO监听的对象。2、调用原来的setter实现。2.3、对比两个类的对象方法。

2501_90256507的博客 1032

微信开发 - 最新第三方网站接入微信登录、微信支付时,本地 redirect_uri 参数错误导致无法调试的解决方案(微信开放平台)完美解决每次都需要部署到线上测试,在本地使用本地 ip 就能轻松调试

redirect_uri参数错误,微信第三方登录,没有服务器时的测试方法,微信开放平台的回调域名怎么设置为本地域名IP,微信登录微信支付每次调试都需要放到服务器上怎么办,微信登录支付业务在本地调试不了怎么办,在本地怎么测试微信支付和登录,微信第三方登陆本地测试,怎么在本地进行测试,微信回调域怎么设置为本地IP,微信扫码登录redirect_uri参数错误,微信开放平台,微信开放平台开发的第三方登录和支付,vue2,nuxt2,vue3,nuxt3,uniapp,微信开放平台,公众号,微信支付,微信登录授权,

🏆 前端领域优质创作者 8791

iOS开发底层之KVO探索下 -18

文章目录一、自定义KVO二、KVO框架 # 前言 提示:本章主要讲自定义KVO 和 优秀的第三方KVO 一、自定义KVO 二、KVO框架

zhonggaorong的专栏 470

手把手教你学simulink实例--基于Simulink的储能系统性能评估与仿真

储能系统是现代能源体系中的关键组成部分,广泛应用于可再生能源并网、电网调峰调频、电力质量改善以及电动汽车充电等领域。为了提高储能系统的运行效率和可靠性,对其性能进行准确评估至关重要。基于MATLAB/Simulink平台,可以构建储能系统的动态模型,并通过仿真分析其在不同工况下的性能表现。本项目旨在研究储能系统的建模方法、控制策略及其性能评估指标,并通过Simulink仿真验证系统的动态特性和稳态性能。

MHD0815的博客 195

基于毫米波生物感知雷达+STM32设计的独居老人居家监护系统(微信小程序)(192)

当前基于STM32设计的独居老人居家监护系统为独居老人提供一种简便、实时的健康监护服务。该系统通过集成多种传感器和功能模块,能够实时监测老人的生理指标、姿态以及室内环境状况,并通过微信小程序远程显示数据,当出现异常情况时及时发出报警提醒。

1万+

iOS——KVO底层学习

* 添加观察者方法 */// 确认观察者实现了 observeValueForKeyPath:ofObject:change:context: 方法return;// 如果没有实现该方法,直接返回// 加锁// 获取路径信息if (pathInfo == nil) // 如果路径信息为空// 创建新的路径信息// 复制路径字符串,使用不可变对象作为键// 插入路径信息到路径映射表// 释放路径信息// 释放路径字符串// 获取观察者数量。

m0_73348697的博客 1427

多维时空数据介绍(4)多维栅格数据构建

上图中包含了经度、纬度和时间三个维度,其变量为经度、纬度、时间以及降雨量,对应的变量单位为东经多少度、北纬多少度、阳历1895-1-1日开始多少天以及每年降雨多少毫升,其中经度数值4个、纬度数值3个、时间数值2个都是一维的数据,而降雨量是一个包含经度、纬度、时间的三维数组,数值有4*3*2=24个。在GeoScene 中NetCDF数据可以用做多种多维时空数据的数据源,进行创建、可视化和分析,它可以是多维栅格数据、时空立方体,还可以是体元图层,区别在于其所要表示的内容和目的。变量又分为坐标变量和属性变量。

你好,我是小张同学! 1286

kvo实现原理_KVO的详解及底层是如何实现的

什么是KVO?一种非正式协议,通知其他对象的指定属性发生了改变。非正式协议:非正式协议是NSObject的一个类别Category,几乎所有的对象都隐含的采用(类别是OC的语言特性,能够给类对象添加方法而不需要创建子类),非正式协议的方法是可选的正式协议: 一个正式协议声明了类需要实现的方法列表,正式协议有自己的声明、采用和类型检查语法。你可以使用@required或者optional关键字指定方...

weixin_42682754的博客 303

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

KVO详解及底层实现

什么是KVO?? KVO就是NSKeyValueObserving,请看官方文档的解释: 大概翻译如下: 一种非正式协议,通知其他对象的指定属性发生了改变。 简单理解就是,可以监听一个对象的某个属性是否发生改变。 那么问题来了,什么是非正式协议??有正式协议吗?? 麻蛋,本来想找官方文档的,找了半天没找到。从Stackoverflow找到了答案,貌似原来官方文档的链接失效了 ...

岑志军的个人博客 675

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

IOS-详解KVO底层实现

一、KVO (Key-Value Observing) KVO 是 Objective-C 对观察者模式(Observer Pattern)的实现。也是 Cocoa Binding 的基础。当被观察对象的某个属性发生更改时,观察者对象会获得通知。 有意思的是,你不需要给被观察的对象添加任何额外代码,就能使用 KVO 。这是怎么做到的? 二、 KVO内部实现原理 KVO是基于ru...

weixin_30847939的博客 111

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

iOS-详解KVO底层实现

前言KVO: Key-Value-Observer,它来源于观察者模式, 其基本思想(copy于某度)是一个目标对象管理所有依赖于它的观察者对象,并在它自身的状态改变时主动通知观察者对象。这个主动通知通常是通过调用各观察者对象所提供的接口方法来实现的。观察者模式较完美地将目标对象与观察者对象解耦。本质当某个类的实例对象的key第一次被观察时,系统就会在运行期动态地创建该类的一个派生类NSKVONo

ZFJ_张福杰 960

IOS KVO底层实现原理 (一)

IOS KVO底层实现原理 (一)一,KVO简述二,KVO探索三,KVO底层原理四,KVO底层实现代码 一,KVO简述 KVO的全称 Key-Value Observing,俗称“键值监听”,可以用于监听某个对象属性值的改变。 带着问题探索: iOS用什么方式实现对一个对象的KVO?(KVO的本质是什么?) 如何手动触发KVO KVO 底层实现是什么? 修改成员变量的值会出发 KVO 吗? KV...

kyl282889543的博客 6627

KVO 底层原理

KVO,全称为Key-Value observing,中文名为键值观察,KVO是一种机制,它允许将其他对象的指定属性的更改通知给对象。 在Key-Value Observing Programming Guide官方文档中,又这么一句话:理解KVO之前,必须先理解KVC(即KVO是基于KVC基础之上,KVO底层也是由KVC实现的) In order to understand key-value observing, you must first understand key-value coding. K

CRMEB小程序商城的博客 6184

iOS窥探KVO底层实现原理篇

Linux编程点击右侧关注,免费入门到精通!作者丨大兵布莱恩特https://www.jianshu.com/p/0aa83ac521ba最近小编公司招聘 iOS, 于是...

<sdffdsfsdfdfs>sfsfsfsdfsdffds</sdfsDS>Fsd 1060

「OC」源码学习——KVO底层原理探究

之前在学习回调传值的时候,就对KVO进行了学习,接下来我们来继续进一步学习KVO之中的相关内容Block 回调的调用位置1. 定义 KVO 核心类与模型@end@end@end@end@end// JCKVO.m#import。

aa2002aa的博客 1180

iOS 手动实现KVO / iOS KVO底层原理

手动实现KVO git demo地址 首先将一下Apple KVO的底层实现吧 内部实现原理 KVO是基于机制实现的,运用了一个技术.就是类型混合指针机制, 将2个对象的isa指针互相调换, 就是俗称的黑魔法. 当某个类的属性对象第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter 方法。派生类在被重写的setter方法内实现真正的通知机制 如果原类为MyPerson,那么生成的派生类名为NSKVONotifying_MyPerson 每个类对象

风起云涌的博客 1030

iOS的KVO底层实现原理

KVO的底层工作原理:   1.准备一个Person对象,作为被监听对象 2.准备一个Observer_Person,作为监听者   @interface ViewController () @property (nonatomic, strong) Person *person; @property (nonatomic, strong) Observer_Person*ob

wddyzzw的专栏 1万+

iOS-底层原理 23:KVO 底层原理

iOS 底层原理 文章汇总 KVO,全称为Key-Value observing,中文名为键值观察,KVO是一种机制,它允许将其他对象的指定属性的更改通知给对象。 在Key-Value Observing Programming Guide官方文档中,又这么一句话:理解KVO之前,必须先理解KVC In order to understand key-value observing, you must first understand key-value coding. 在iOS日常开发中,经常使用.

lin1109221208的博客 1094

KVO 底层实现原理

一 、 基本使用 概述 KVO全称NSKeyValueObserving,是一个非正式协议,它定义了对象之间观察和通知状态改变的通用机制的。允许对象监听另一个对象特定属性的改变,并在改变时接收到事件。由于KVO的实现机制,所以对属性才会发生作用,一般继承自NSObject的对象都默认支持KVO。 在 Objective-C 和 Cocoa 中,有许多事件之间进行通信的方式,并且每个都有不同程度的形...

Walden_tinghou的专栏 874
上一篇: Mac搭建nginx+rtmp服务器
下一篇: 使用WKWebView替换UIWebView
Levilly
博客等级 码龄10年 6粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值