iOS用什么方式实现对一个对象的KVO?(KVO的本质是什么?)
先给答案,我们再探具体:
利用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的本质是什么?)相关推荐
- 终于明白那些年知其然而不知其所以然的iOS内存管理方式
终于明白那些年知其然而不知其所以然的iOS内存管理方式 前言 从我开始学习iOS的时候,身边的朋友.网上的博客都告诉我iOS的内存管理是依靠引用计数的,然后说引用计数大于1则对象保存在内存的堆中而引用 ...
- 微信公众号内下载pdf等文件,受微信所限制,安卓和IOS不同处理方式(最最最优版)
继上一篇文章微信公众号内下载pdf等文件,受微信所限制,安卓和IOS不同处理方式 后觉得还有更好的解决办法,这次真的找到更加优化版本,一定需要后台配合才行:后台接口返回Blob,后端设置respons ...
- iOS crash 定位方式
文章目录 iOS crash 定位方式 1. symbolicatecrash 定位 2. atos 定位 iOS crash 定位方式 1. symbolicatecrash 定位 在iOS 中系统 ...
- iOS In House方式发布
这两天In House签名的时候,提示SSL证书过期了.又折腾了一把iOS In House方式发布.这里开一篇文章记录一下过去折腾In House的经过,未来再修改也更新在这里. 最早在12年的时候 ...
- ios::app与ios::ate打开方式有什么不同??
看一个资料上说: 1.ios::app ----写入的数据将被追加在文件的末尾,此方式使用ios::out 2.ios::ate ----写入的数据将被追加在文件的末尾,此方式不使 ...
- iOS 数据持久化方式 - 归档 反归档
所谓归档:将复杂对象转化为NSData类型数据(复杂-->归档-->NSData--->WriteToFile) 注意:归档是将对象转化为数据字节,以文件的形式存储在磁盘上, 所谓反 ...
- 微信公众号内下载pdf等文件,受微信所限制,安卓和IOS不同处理方式
前言: IOS手机可以直接下载文件,但是需要后端设置Content-Disposition和Content-Type 安卓手机只能打开其他浏览器下载,(别问我怎么知道的,试出来的结果),所以跳转至中专 ...
- ios 4种方式防护label.text = @(100)崩溃
服务器在给客户端接口的时候一般是json,正常情况下约定是NSString类型,但是有时候服务器给到就是NSNumber类型.如果是需要展示的数据,label.text = @(100),这样就会崩溃 ...
- ios隐藏标题栏方式
info.plist View controller-based status bar appearance NO xcode 设置 Hide status bar 选中
最新文章
- mysql语句使用_MySQL语句的使用
- MySQL分组查询—添加排序
- jzoj4252-QYQ的图【dfs】
- android安装过哪些应用程序,如何安装应用程序两次而不干扰Android?
- 04. 二维数组中的查找
- bootice添加linux_如何使用老毛桃winpe的Bootice工具新建实模式启动项(Grub/Linux)?
- 7. 锁定框架(The Locking Framework)
- Azure Machine Learning的新特性
- 17-(基础入门篇)GPRS(Air202)串口
- CodeBlock 基本使用
- 手机号中间四位变成****
- DNS测试 nslookup
- 浅谈软件测试测试策略几点总结内容
- php模板修改教程,商业模板修改高级教程
- ubuntu redis desktop manager 编译问题解决
- 兔子与兔子 字符串hash
- python画图设置坐标轴为科学记数法_防止matplotlib.pyplot中的科学记数法
- vue 生成海报完整代码, (包括远程图片转base64、html2canvas 在IOS系统兼容的解决办法)
- 湖科大 2022大三上 软件工程复习资料
- word中图形或文本框的组合问题
热门文章
- 作业4(列表增加或者修改)
- MySQL 单表百万数据记录分页性能优化
- 科普:WiFi是谁申请的专利?高通吗?错!
- Swift - 使用网格(UICollectionView)的自定义布局实现复杂页面
- C#线程系列(3):线程池和文件下载服务器
- 解决javascript动态改变img的src属性图片不显示问题
- Google Maps Android API V2的使用及问题解决
- Host ‘XXX‘ is not allowed to connect to this MySQL server 解决方案/如何开启MySQL的远程帐号
- Mockito测试void方法会引发异常
- 如何显示jQuery中的加载微调器?