【OC底层】OC对象本质,如 isa, super-class
Objective-C的本质
2、在OC中的所有面向对象的实现,都是基于C/C++的数据结构实现的
3、将Objective-C代码转换为C\C++代码
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的CPP文件
注:如果需要链接其他框架,使用-framework参数。比如-framework UIKit
一个OC对象在内存中是如何布局的?
NSObject基类的实现:
子类的实现:
子类的拆解:
1、在OC中的对象,就是 C++中的 struct来实现的
2、每个OC对象中都会有一个 isa 的指针,isa指向的是 objc_class 结构体,如下(旧版OC原码):
通过代码可以看得出在OC2 中已经不能通过 objc_method_list 之类的方式获取方法名、实例、协议之类的了,需要使用新的方法获取
思路:自定义一个和oc源码中 objc_class 结构一样的结构体,然后将对象的isa 强转成我们自定义的那个,再去调用
如下是OC中objc_class的源码(新版OC原码):
新的OC版本中方法、属性、协议相关数据都存在了 bits
通过 bits.data() 返回 class_rw_t 结构,如下:
bits.data() 的实现:
其中需要 通过 & FAST_DATA_MASK 才能获取到真实的地址
整体数据结构图:
OC对象的分类
Objective-C对象主要分为以下3类:
1> instance对象(实例对象)
2> class对象(类对象)存储实例方法列表等信息
3> meta-class对象(元类对象)存储类方法列表等信息
通过下面的代码可以分别获取3种对象:
NSObject* obj = [[NSObject alloc]init];const char* className = [@"NSObject" cStringUsingEncoding:NSUTF8StringEncoding];// 实例对象NSLog(@"instance: %p",obj);// 类对象NSLog(@"NSObject class: %p", [NSObject class]);// 同上NSLog(@"obj class: %p", [obj class]);// 如果传实例对象,获取到的还是类对象NSLog(@"get class: %p", object_getClass(obj));// 通过类名获取类对象NSLog(@"objcClass: %p", objc_getClass(className));// 元类对象// 必需要传入类对象才能获取元类对象NSLog(@"meta-class: %p", object_getClass([obj class]));// 通过类名获取元类对象NSLog(@"objcMetaClass: %p", objc_getMetaClass(className));// 判断是否是metaClassNSLog(@"isMetaClass1:%i",class_isMetaClass([NSObject class])); // 0NSLog(@"isMetaClass2:%i",class_isMetaClass([[NSObject class] class])); // 0NSLog(@"isMetaClass3:%i",class_isMetaClass(object_getClass([NSObject class]))); // 1
输出:
2018-09-27 14:39:37.363 OC_isa_supclass[1350:102454] instance: 0x100202b50 2018-09-27 14:39:37.364 OC_isa_supclass[1350:102454] NSObject class: 0x7fff760140f0 2018-09-27 14:39:37.364 OC_isa_supclass[1350:102454] obj class: 0x7fff760140f0 2018-09-27 14:39:37.364 OC_isa_supclass[1350:102454] get class: 0x7fff760140f0 2018-09-27 14:39:37.365 OC_isa_supclass[1350:102454] objcClass: 0x7fff760140f0 2018-09-27 14:39:37.365 OC_isa_supclass[1350:102454] meta-class: 0x7fff76014118 2018-09-27 14:39:37.365 OC_isa_supclass[1350:102454] objcMetaClass: 0x7fff760141182018-09-27 14:49:27.746 OC_isa_supclass[1360:106109] isMetaClass1:02018-09-27 14:49:27.746 OC_isa_supclass[1360:106109] isMetaClass2:02018-09-27 14:49:27.746 OC_isa_supclass[1360:106109] isMetaClass3:1
1> 需要注意的是 object_getClass 方法,当传入的是实例对象,就会返回类对象,如果传入的是类对象就会返回元类对象
2> 还有一点就是 [[NSObject class] class] 这样是获取不到元类对象的,这样获取到的还是类对象
3> 另外里面还有两个 objc_ 开头的方法,分别是获取类对象和元类对象,但它是传入类名字符串就可以了,需要转换成 C语言的char
1、instance对象
它们是不同的两个对象,分别占据着两块不同的内存
instance对象在内存中保存的信息包括:
1> isa指针
2> 其它成员变量
2、class对象
NSObject类对象只有一个,所有实例对象的class属性获取到的都是同一个类对象
class对象在内存中存储的信息主要包括:
1> isa指针
2> superclass指针
3> 类的属性信息(@property)、类的对象方法信息(instance method)
4> 类的协议信息(protocol)、类的成员变量信息(ivar)
....
3、meta-class对象
每个类在内存中有且只有一个meta-class对象
meta-class对象在内存中存储的信息主要包括:
1> isa指针
2> superclass指针
3> 类的类方法信息(class method)
...
注:class 对象和 meta-class 对象都是 Class 类型的,它们其实结构都是一样的,class对象中一样会包含 类方法,只不过那个类方法是 空的而已。
同样,meta-class对象中也有 类的属性、对象方法、协议、成员变量,不过那些对应的值也都是空
isa指针
上面我们通过源码可以看到每个对象都有一个 isa 指针,isa指针作用是干嘛的呢?
通过上图可以看出:
1> instance的isa指向class
当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用
2> class的isa指向meta-class
当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用
class对象的superclass指针
superclass是用于找父类的,比如子类调用某个方法,如果子类中没有,就会去父类找,底层就是通过superclass找到父类的,如下图:
当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用
meta-class对象的superclass指针
meta-class中的superclass基本和 class对象中的一样,不过有一点点区别,如图:
当Student的class要调用Person的类方法时,会先通过isa找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用
有什么区别呢?从这图可能看不出来,区别就是如果基类的meta-class中都找不到类方法,那么它就会去从基类对象里面去找对象方法,OC的底层其实是不区分 对象方法与类方法的。
isa、superclass总结
这张图能够清楚的描述 isa和superclass的作用和关系,下面是备注了一下,看得更加懂点。
- instance的isa指向的是class对象
- class的isa指向的是meta-class对象
- 所有的meta-class的isa指向的都是基类的meta-class对象(重点)
- class的superclass指向的是父类的class对象,如果没有父类,superclass指针为nil
- meta-class的superclass指向的是父类的meta-class对象
- 基类的meta-class的superclass指向的是基类的class对象(重点)
instance调用对象方法的轨迹:
实例对象会先通过isa找到class对象,判断里面有没有要调用的方法,如果有就直接调用,没有就会通过class对象中的superclass找到父类,然后在父类中判断是否有该方法,如果还没有就接着往上找。
class调用类方法的轨迹:
isa找meta-class,方法不存在,就通过superclass找父类,最后基类mate-class也没有的话还会去基类对象找,这样就会导致调用类方法可能会去调用实例对象的方法
isa指针的一些问题
上面已经说到了instance对象的isa指针指向的是class对象,那就是说instance对象的isa指针内存地址是不是就是class对象的内存地址呢?
如果在以前的32位系统中确实如此,在64位系统中不是的,里面有一个点操作, ISA_MASK
其中arm64和x86架构的这个 ISA_MASK的偏移地址是不一样的,如下图:
class、meta-class对象的本质结构都是struct objc_class,如下图:
-----------------------------
本文参考借鉴MJ的教程视频,非常感谢.
转载于:https://www.cnblogs.com/xgao/p/9708163.html
【OC底层】OC对象本质,如 isa, super-class相关推荐
- iOS对象本质及isa
文章目录 前言 一.对象的本质是什么? 1.对象的本质 2.name的set与get方法 二.isa分析 1.联合体 2.位域 3.isa关联指针与类 a.通过掩码来还原类信息 b.通过位运算还原类信 ...
- OC底层消息转发机制
目录 1. 前言 2. 动态方法决议 2.1 实例方法动态决议 2.2 类方法动态决议 3. 消息转发 3.1 快速转发流程 3.2 慢速转发流程 4. 总结 1. 前言 上一篇文章(OC底层方法的本 ...
- MJiOS底层笔记--OC对象本质
本文属笔记性质,主要针对自己理解不太透彻的地方进行记录. 推荐系统直接学习小码哥iOS底层原理班---MJ老师的课确实不错,强推一波. OC对象本质 基于C与C++结构体实现 OC语言如何被编译器编译 ...
- 浅谈OC中Block的本质
Block简介 block是将函数及其执行上下文封装起来的一个对象 在block实现的内部,有很多变量,因为block也是一个对象 其中包含了诸如isa指针,imp指针等对象变量,还有储存其截获变量的 ...
- OC底层探索(七) cache_t分析
cache_t 源码 在OC底层探索(五) 类的结构分析文章中,我们分析objc_class源码时,有提到过其属性 cache_t cache属性的大小为16字节. 那么我们今天就着重分析以下cach ...
- OC底层探索(二十二)八大锁
OC底层文章汇总 锁的种类 在OC中锁分为互斥锁和自旋锁两种. 互斥锁 用于保护临界区,确保同一时间,只有一条线程能够执行 如果代码中只有一个地方需要加锁,大多都使用 self,这样可以避免单独再创建 ...
- OC底层原理之Runtime
本系列主要是看完MJ的OC底层原理课程所写的总结,希望自己能加深对iOS底层的了解. OC的信息机制 OC中的方法调用其实都是转成objc_msgSend函数的调用,给receiver(方法调用者)发 ...
- OC基础--OC中的类方法和对象方法
PS:个人感觉跟C#的静态方法和非静态方法有点类似,仅仅是有点类似.明杰老师说过不要总跟之前学过的语言做比较,但是个人觉得,比较一下可以加深印象吧.重点是自己真的能够区分开! 一.OC中的对象方法 1 ...
- oc总结 --oc基础语法相关知识
m是OC源文件扩展名,入口点也是main函数,第一个OC程序: #import <Foundation/Foundation.h> int main(int argc, const cha ...
最新文章
- R语言数据结构之数组
- C/C++经典程序训练3---模拟计算器_JAVA
- CNCF宣布Envoy项目正式毕业
- 用户微服务表结构介绍
- RHEL5实现YUM本地源的配置
- Chromium内核原理之网络栈HTTP Cache
- 如何基于对话框的project基于改变BCG的
- 读《scikiit-learn机器学习》支持向量机
- 一文搞懂Spring Cloud Zuul
- 算法设计与分析——图像的压缩
- Firefox中文版与英文版转换
- tcp 抓包出现spurious retransmission
- MacBook连接打印机-惠普HP LaserJet Pro MFP M427fdn 连接方法
- wc与xargs命令
- apache(Web服务器)
- Android开发中自定义表情并发送出去之经典的发送表情
- Excel房贷计算器
- 数学脱式计算在线计算机,四年级数学脱式计算练习400题
- Android小图标
- Boom 3D官方汉化免费下载激活版
热门文章
- 栈溢出笔记1.10 基于SEH的栈溢出
- Python 链表内取随机数(list取随机数)
- Python解决爬虫中文返回乱码问题
- 2019-05-27 Java学习日记 day17
- jpa-spring -basic
- 使用Huploadify上传文件并动态传递参数到后台
- [原]openstack-kilo--issue(十八) Error parsing template file: Template format version not found.
- Nginx的配置中与流量分发相关的配置规范:
- 干货收藏!Python完整代码带你一文看懂抽样
- linux下SD卡烧录程序