博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
KVC/KVO的内部实现
阅读量:6766 次
发布时间:2019-06-26

本文共 2161 字,大约阅读时间需要 7 分钟。

KVC的内部实现

KVC运用了isa-swizzing技术。isa-swizzing就是类型混合指针机制。KVC通过isa-swizzing实现其内部查找定位。

isa指针(is kind of 的意思)指向维护分发表的对象的类,该分发表实际上包含了指向实现类中的方法的指针和其他数据。

 [site setValue:@"sitename" forKey:@"name"] //会被编译器处理成 SEL sel = sel_get_uid(setValue:forKey); IMP method = objc_msg_loopup(site->isa,sel); method(site,sel,@"sitename",@"name");  

  • 每个类都有一张方法表,是一个hash表,值是还书指针IMP,SEL的名称就是查表时所用的键。
  • SEL数据类型:查找方法表时所用的键。定义成char*,实质上可以理解成int值。
  • IMP数据类型:他其实就是一个编译器内部实现时候的函数指针。当Objective-C编译器去处理实现一个方法的时候,就会指向一个IMP对象,这个对象是C语言表述的类型。

KVC的内部机制:

一个对象在调用setValue的时候进行了如下操作:

  • 根据方法名找到运行方法的时候需要的环境参数
  • 他会从自己的isa指针结合环境参数,找到具体的方法实现接口。
  • 再直接查找得来的具体的实现方法

KVO概述

键值观察Key-Value-Observer就是观察者模式。

  • 观察者模式的定义:一个目标对象管理所有依赖于它的观察者对象,并在它自身的状态改变时主动通知观察者对象。这个主动通知通常是通过调用各观察者对象所提供的接口方法来实现的。观察者模式较完美地将目标对象与观察者对象解耦。 当需要检测其他类的属性值变化,但又不想被观察的类知道,有点像FBI监视嫌疑人,这个时候就可以使用KVO了。

KVO同KVC一样都依赖于Runtime的动态机制

  • 注册:      -(void)addobserver:(nsobject*)anobserer forkeypath:(nsstrig*)keypath options:(nskeyValueObservingOptions)options context:(void*)context{}  
  • 实现方法: -(void)observerValueForKeyPath:(nsstrig*)keypath ofOject:(id)object change:(nsdictionary*)change context:(void*)context
  • 移除: -(void)removeObsever:(nsobject)observer forkeypath:(nsnsting*)keypath;

KVO实现步骤

注册//keyPath就是要观察的属性值//options给你观察键值变化的选择//context方便传输你需要的数据-(void)addObserver:(NSObject *)anObserver         forKeyPath:(NSString *)keyPath            options:(NSKeyValueObservingOptions)options            context:(void *)context    实现方法//change里存储了一些变化的数据,比如变化前的数据,变化后的数据;如果注册时context不为空,这里context就能接收到。-(void)observeValueForKeyPath:(NSString *)keyPath                      ofObject:(id)object                       change:(NSDictionary *)change                       context:(void *)context    移除- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;复制代码

系统实现KVO有以下几个步骤:

  • 当类A的对象第一次被观察的时候,系统会在运行期动态创建类A的派生类。我们称为B。
  • 在派生类B中重写类A的setter方法,B类在被重写的setter方法中实现通知机制。 类B重写会 class方法,将自己伪装成类A。类B还会重写dealloc方法释放资源。
  • 系统将所有指向类A对象的isa指针指向类B的对象。
  • KVO同KVC一样,通过 isa-swizzling 技术来实现。当观察者被注册为一个对象的属性的观察对象的isa指针被修改,指向一个中间类,而不是在真实的类。其结果是,isa指针的值并不一定反映实例的实际类。

所以不能依靠isa指针来确定对象是否是一个类的成员。应该使用class方法来确定对象实例的类。

转载于:https://juejin.im/post/5b8f8fece51d450e6a2dcbfa

你可能感兴趣的文章
Java输入两个正整数m和n,求其最大公约数和最小公倍数。
查看>>
在Solaris 10编译并安装vim7.3
查看>>
Java中抽象类、接口、父类直接的区别与联系
查看>>
Google Chrome OS 将来能取代 Windows 帝国吗?
查看>>
设计原则二:空间和图底关系
查看>>
IPV6IPV4双栈协议DNS解析抓包分析
查看>>
“WCF并发与限流体”系列[共7篇]
查看>>
LVS集群之十种调度算法及负载均衡--理论
查看>>
shell 脚本监控Linux 性能
查看>>
RedHat搭建Samba服务器
查看>>
查询SQL Server system session ID?
查看>>
IDEA或Webstorm设置Ctrl+滚轮调整字体大小
查看>>
String[]转String
查看>>
【远程用户建立】
查看>>
各种编程语言下字符串分割及foreach遍历对比
查看>>
MySQL常用操作基本操作
查看>>
秒开缓存服务器详细介绍
查看>>
WebGoat题目解答(General~XSS)
查看>>
网页页面 自动刷新的3种代码
查看>>
Android 实现推送功能
查看>>