runtime笔记|runtime笔记 之 类与对象基础数据结构
运行时简介
Objective-C
语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理。
对于Objective-C
来说,这个运行时系统就像一个操作系统一样:它让所有的工作可以正常的运行。Runtime
基本上是用C
和汇编
写的,这个库使得C
语言有了面向对象的能力。
在Runtime
中,对象可以用C
语言中的结构体表示,而方法可以用C
函数来实现,另外再加上了一些额外的特性。这些结构体和函数被runtime
函数封装后,让OC
的面向对象编程变为可能。
找出方法的最终执行代码:当程序执行[object doSomething]
时,会向消息接收者(object)
发送一条消息(doSomething)
,runtime
会根据消息接收者是否能响应该消息而做出不同的反应。
类与对象基础数据结构
Objective-C
中的类是由Class
类型结构表示的,它是一个指向objc_class
结构体的指针,如下,
在objc.h
中
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
在
runtime.h
中可以查看objc_class
的定义struct objc_class {
Class _Nonnull isaOBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_classOBJC2_UNAVAILABLE;
//父类
const char * _Nonnull nameOBJC2_UNAVAILABLE;
//类名
long versionOBJC2_UNAVAILABLE;
//类的版本信息,默认为0
long infoOBJC2_UNAVAILABLE;
//类信息,供运行期使用的一些位标识
long instance_sizeOBJC2_UNAVAILABLE;
//类信息,供运行期使用的一些位标识
struct objc_ivar_list * _Nullable ivarsOBJC2_UNAVAILABLE;
//该类的成员变量链表
struct objc_method_list * _Nullable * _Nullable methodListsOBJC2_UNAVAILABLE;
//方法定义的链表
struct objc_cache * _Nonnull cacheOBJC2_UNAVAILABLE;
//方法缓存
struct objc_protocol_list * _Nullable protocolsOBJC2_UNAVAILABLE;
//协议链表
#endif} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */
objc_object
objc_object
是一个表示类的实例的结构体指针,在objc.h
中可以查看它的定义,如下/// Represents an instance of a class.
struct objc_object {
Class _Nonnull isaOBJC_ISA_AVAILABILITY;
};
/// A pointer to an instance of a class.
typedef struct objc_object *id;
由上可以看到,这个结构只有一个指针,即指向其类的
isa
指针。当我们向一个
Objective-C
对象发送消息时,runtime
库会根据实例对象的isa
指针找到这个实例对象所属的类。而后,runtime
库会在这个类的方法列表以及其父类的方法列表去寻找与消息对应的selctor
所指向的方法,最后运行这个方法。元类
Meta Class
meta-class
是一个类本身对象所属的类。- 所有的类本身也是一个对象,我们可以向这个对象发送消息,即调用类方法。
- 既然是对象,那么它也是一个
objc_object
指针,包含一个指向其类的isa
指针,那么这个isa
指针又指向哪里呢? - 为了调用类方法,这个类的
isa
指针必须指向一个包含这些类方法的一个objc_class
结构体。这就引出了meta-class
的概念,meta-class
中存储着一个类的所有类方法。
isa
指针指向的就是meta-class
。- 当我们向一个对象发送消息时,
runtime
会在这个对象所属的这个类的方法列表中查找方法;而向一个类发送消息时,会在这个类的meta-class
的方法列表中查找。
- 再深入一下,
meta-class
也是一个类,也可以向它发送一个消息,那么它的isa
又是指向哪里呢?为了不让这种结构无限延伸下去,Objective-C
的设计者让所有的meta-class
的isa
指向基类的meta-class
,以此作为它们的所属类。
任何通过上面的描述,再加上对NSObject
继承体系下的meta-class
都使用NSObject
的meta-class
作为自己的所属类,
而基类的meta-class
的isa
指针是指向它自己。
objc_class
结构体中super_class
指针的分析,我们就可以描绘出类及相应meta-class
类的一个继承体系图了,如下文章图片
继承体系图
Category
Category
是表示一个指向分类的结构体的指针,如下,在
runtime.h
中struct objc_category {
char * _Nonnull category_nameOBJC2_UNAVAILABLE;
//分类名
char * _Nonnull class_nameOBJC2_UNAVAILABLE;
//分类所属的类名
struct objc_method_list * _Nullable instance_methodsOBJC2_UNAVAILABLE;
//实例方法列表
struct objc_method_list * _Nullable class_methodsOBJC2_UNAVAILABLE;
//类方法列表
struct objc_protocol_list * _Nullable protocolsOBJC2_UNAVAILABLE;
、//分类所实现的协议的列表
}OBJC2_UNAVAILABLE;
这个结构体主要包含了分类定义的实例方法与类方法,其中
instance_methods
列表是objc_class
中方法列表的一个子集,而class_methods
列表是元类方法列表的一个子集。可以发现,类别中没有
ivar
成员变量指针,也就意味着:类别中不能够添加实例变量和属性。struct objc_ivar_list *ivarsOBJC2_UNAVAILABLE;
// 该类的成员变量链表
【runtime笔记|runtime笔记 之 类与对象基础数据结构】上面的内容来源自宇杰笔记的这一篇文章:iOS运行时(Runtime)详解+Demo。我也是一边理解一边写的。
推荐阅读
- PMSJ寻平面设计师之现代(Hyundai)
- EffectiveObjective-C2.0|EffectiveObjective-C2.0 笔记 - 第二部分
- 太平之莲
- 闲杂“细雨”
- 七年之痒之后
- 深入理解Go之generate
- 由浅入深理解AOP
- 期刊|期刊 | 国内核心期刊之(北大核心)
- 生活随笔|好天气下的意外之喜
- 感恩之旅第75天