文章目录
- iOS - Runtime - Class的结构
- 前言
- 1. Class的结构
- 1.1 Class的结构
- 1.1.1 objc_class
- 1.1.2 class_rw_t
- 1.1.3 class_ro_t
- 1.2 class_rw_t和class_ro_t的区别
- 1.3 class_rw_t和class_ro_t的关系
- 1.3.1 分析关系
- 1.3.2 原因
- 1.4 method_t
- 1.4.1 Type Encoding
- 1.4.2 types说明
- 1.4.2.1 - (void)test
- 1.4.2.2 - (void)test:(NSString *)name
iOS - Runtime - Class的结构
前言
1. Class的结构
前面我们学习OC对象的时候,了解了class
类对象、meta-class
元类对象
实际上,class
类对象、meta-class
元类对象底层结构体都是class
,元类对象
可以认为是特殊的类对象
。他们底层结构是一样的,只不过存储的内容有所区别
1.1 Class的结构
Class的结构如下图所示:
1.1.1 objc_class
里面存储了
isa
superclass
cache
bits
其中的bits
,& FAST_DATA_MASK
位运算之后,拿到class_rw_t
,class_rw_t
里面的ro
则是class_ro_t
1.1.2 class_rw_t
class_rw_t
里面的methods
、properties
、protocols
是二维数组,是可读可写
的,包含了类的初始内容
、分类的内容
1.1.3 class_ro_t
class_ro_t
里面的baseMethodList
、baseProtocols
、ivars
、baseProperties
是一维数组,是只读
的,包含了类的初始内容
1.2 class_rw_t和class_ro_t的区别
对于他们里面的主要内容:
class_rw_t
:methods
、properties
、protocols
class_ro_t
:baseMethodList
、baseProtocols
、ivars
、baseProperties
区别主要是:
class_rw_t
的主要成员是二维数组
,class_ro_t
的主要成员是一维数组
class_rw_t
的主要成员是可读可写的,class_ro_t
是只读的
1.3 class_rw_t和class_ro_t的关系
class_rw_t
和class_ro_t
里面的结构很像,但是class_ro_t
的成员基本上带了base
。
1.3.1 分析关系
其实刚开始的时候不存在rw
的,class里面的东西都保存在ro
里面,bits
取出来的其实是ro
,rw
是后面才生成的
因为rw
是可读可写的,生成的时候,会把ro
里面的东西合并进去,然后把rw
设置为datacls->setData(rw)
,此时rw
就替换了原本ro
的位置,同时rw
把ro属性指向原来的ro
对象
1.3.2 原因
class_rw_t
里面的数据基本上是二维数组,并且是可读可写。
我们知道分类
的东西是runtime
阶段才附加进去的,在将分类
的东西合并到class
里面的时候。
因此他们之间是相互配合的,class_ro_t
先是存储了编译期间固定
的东西,运行时一些动态
的东西则是存入class_rw_t
,class_rw_t
在初始化前会将class_ro_t
的东西先附加进去。于是class_rw_t
里面就有完整的东西
1.4 method_t
method_t
是对方法
\函数
的封装
IMP
代表函数的具体实现
SEL
代表方法\函数名
,一般叫做选择器
,底层结构跟char *
类似- 可以通过
@selector()
和sel_registerName()
获得 - 可以通过
sel_getName()
和NSStringFromSelector()
转成字符串 不同类
中相同名字
的方法,所对应的方法选择器
是相同
的
- 可以通过
- types包含了函数返回值、参数编码的字符串
返回值 | 参数1 | 参数2 | … | 参数n |
---|
1.4.1 Type Encoding
iOS中提供了一个叫做@encode的指令,可以将具体的类型表示成字符串编码
1.4.2 types说明
使用Xcode 12.5.1 iPhone(12.4)模拟器
1.4.2.1 - (void)test
方法- (void)test;
对应的types
是v16@0:8
- (void)test;
实际上C语言函数为:- (void)test:(id)self _cmd:(SEL)_cmd
,包含self
、_cmd
两个参数
于是types
表示如下表:
v | 16 | @ | 0 | : | 8 |
---|---|---|---|---|---|
void 无返回值 | 2 个参数共16字节 | 第1 个参数:id 类型 | 第1 个参数:从0 字节开始 | 第2 个参数:SEL 类型 | 第2 个参数:从8 字节开始 |
1.4.2.2 - (void)test:(NSString *)name
给test
方法增加一个name参数,此时types
是v24@0:8@16
types
表示如下表:
于是types
表示如下表:
v | 24 | @ | 0 | : | 8 | @ | 16 |
---|---|---|---|---|---|---|---|
void 无返回值 | 3 个参数共24字节 | 第1 个参数:id 类型 | 第1 个参数:从0 字节开始 | 第2 个参数:SEL 类型 | 第2 个参数:从8 字节开始 | 第3 个参数:id 类型 | 第3 个参数:从16 字节开始 |
@oubijiexi