先给答案,我们再探具体:

利用RuntimeAPI动态生成一个子类,并且让instance对象的isa指向这个全新的子类

当修改instance对象的属性时,会调用Foundation的_NSSetXXXValueAndNotify函数

willChangeValueForKey:

父类原来的setter

didChangeValueForKey:

内部会触发监听器(Oberser)的监听方法( observeValueForKeyPath:ofObject:change:context:)

我们要手动触发kvo的话,就调用willChangeValueForKey: 和didChangeValueForKey: 方法

我们创建一个person对象,并含有age属性,赋值1,添加监听方法,在touchsbegin方法里面改变age的值,

实现监听方法,我们在添加kvo监听前,分别打印person1的类对象的值,如下

我们发现打印不同,添加监听后,新生成一个类NSKVONotifying_Peerson类对象,根据我们之前学的isa指针,实例对象的isa指针指向他的类对象,我们可以用下图表示,

在这个新生成的类对象里面实现的就是

- (void)setAge:(int)age
{_NSSetIntValueAndNotify();
}// 伪代码
void _NSSetIntValueAndNotify()
{[self willChangeValueForKey:@"age"];[super setAge:age];[self didChangeValueForKey:@"age"];
}- (void)didChangeValueForKey:(NSString *)key
{// 通知监听器,某某属性值发生了改变[oberser observeValueForKeyPath:key ofObject:self change:nil context:nil];
}

有人会问我们为什么知道是调用了_NSSetIntValueAndNotify()这个函数,接下来就来验证,

 // [self.person1 methodForSelector:@selector(setAge:)] 这个为获得IMP
NSLog(@"person1添加KVO监听之前 - %p %p",[self.person1 methodForSelector:@selector(setAge:)],[self.person2 methodForSelector:@selector(setAge:)]);//打印为 person1添加KVO监听之前 - 0x10935f630 0x10935f630// 给person1对象添加KVO监听NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;[self.person1 addObserver:self forKeyPath:@"age" options:options context:@"123"];NSLog(@"person1添加KVO监听之后 - %p %p",[self.person1 methodForSelector:@selector(setAge:)],[self.person2 methodForSelector:@selector(setAge:)]);
// 打印为person1添加KVO监听之后 - 0x1096ba3d2 0x10935f630

在这里打断点,在lldb里面打印 p (IMP)0x1096ba3d2 这样就会打印对应的方法 :(IMP) $0 = 0x00000001096ba3d2 (Foundation`_NSSetIntValueAndNotify),从这里我们就看到了是调用_NSSetIntValueAndNotify函数。在这里在附上kvc赋值和取值的原理:

iOS用什么方式实现对一个对象的KVO?(KVO的本质是什么?)相关推荐

  1. 终于明白那些年知其然而不知其所以然的iOS内存管理方式

    终于明白那些年知其然而不知其所以然的iOS内存管理方式 前言 从我开始学习iOS的时候,身边的朋友.网上的博客都告诉我iOS的内存管理是依靠引用计数的,然后说引用计数大于1则对象保存在内存的堆中而引用 ...

  2. 微信公众号内下载pdf等文件,受微信所限制,安卓和IOS不同处理方式(最最最优版)

    继上一篇文章微信公众号内下载pdf等文件,受微信所限制,安卓和IOS不同处理方式 后觉得还有更好的解决办法,这次真的找到更加优化版本,一定需要后台配合才行:后台接口返回Blob,后端设置respons ...

  3. iOS crash 定位方式

    文章目录 iOS crash 定位方式 1. symbolicatecrash 定位 2. atos 定位 iOS crash 定位方式 1. symbolicatecrash 定位 在iOS 中系统 ...

  4. iOS In House方式发布

    这两天In House签名的时候,提示SSL证书过期了.又折腾了一把iOS In House方式发布.这里开一篇文章记录一下过去折腾In House的经过,未来再修改也更新在这里. 最早在12年的时候 ...

  5. ios::app与ios::ate打开方式有什么不同??

    看一个资料上说:   1.ios::app    ----写入的数据将被追加在文件的末尾,此方式使用ios::out   2.ios::ate    ----写入的数据将被追加在文件的末尾,此方式不使 ...

  6. iOS 数据持久化方式 - 归档 反归档

    所谓归档:将复杂对象转化为NSData类型数据(复杂-->归档-->NSData--->WriteToFile) 注意:归档是将对象转化为数据字节,以文件的形式存储在磁盘上, 所谓反 ...

  7. 微信公众号内下载pdf等文件,受微信所限制,安卓和IOS不同处理方式

    前言: IOS手机可以直接下载文件,但是需要后端设置Content-Disposition和Content-Type 安卓手机只能打开其他浏览器下载,(别问我怎么知道的,试出来的结果),所以跳转至中专 ...

  8. ios 4种方式防护label.text = @(100)崩溃

    服务器在给客户端接口的时候一般是json,正常情况下约定是NSString类型,但是有时候服务器给到就是NSNumber类型.如果是需要展示的数据,label.text = @(100),这样就会崩溃 ...

  9. ios隐藏标题栏方式

    info.plist View controller-based status bar appearance NO xcode 设置 Hide status bar 选中

最新文章

  1. mysql语句使用_MySQL语句的使用
  2. MySQL分组查询—添加排序
  3. jzoj4252-QYQ的图【dfs】
  4. android安装过哪些应用程序,如何安装应用程序两次而不干扰Android?
  5. 04. 二维数组中的查找
  6. bootice添加linux_如何使用老毛桃winpe的Bootice工具新建实模式启动项(Grub/Linux)?
  7. 7. 锁定框架(The Locking Framework)
  8. Azure Machine Learning的新特性
  9. 17-(基础入门篇)GPRS(Air202)串口
  10. CodeBlock 基本使用
  11. 手机号中间四位变成****
  12. DNS测试 nslookup
  13. 浅谈软件测试测试策略几点总结内容
  14. php模板修改教程,商业模板修改高级教程
  15. ubuntu redis desktop manager 编译问题解决
  16. 兔子与兔子 字符串hash
  17. python画图设置坐标轴为科学记数法_防止matplotlib.pyplot中的科学记数法
  18. vue 生成海报完整代码, (包括远程图片转base64、html2canvas 在IOS系统兼容的解决办法)
  19. 湖科大 2022大三上 软件工程复习资料
  20. word中图形或文本框的组合问题

热门文章

  1. 作业4(列表增加或者修改)
  2. MySQL 单表百万数据记录分页性能优化
  3. 科普:WiFi是谁申请的专利?高通吗?错!
  4. Swift - 使用网格(UICollectionView)的自定义布局实现复杂页面
  5. C#线程系列(3):线程池和文件下载服务器
  6. 解决javascript动态改变img的src属性图片不显示问题
  7. Google Maps Android API V2的使用及问题解决
  8. Host ‘XXX‘ is not allowed to connect to this MySQL server 解决方案/如何开启MySQL的远程帐号
  9. Mockito测试void方法会引发异常
  10. 如何显示jQuery中的加载微调器?