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-classisa指向基类的meta-class,以此作为它们的所属类。
任何NSObject继承体系下的meta-class都使用NSObjectmeta-class作为自己的所属类,
而基类的meta-classisa指针是指向它自己。
通过上面的描述,再加上对objc_class结构体中super_class指针的分析,我们就可以描绘出类及相应meta-class类的一个继承体系图了,如下

runtime笔记|runtime笔记 之 类与对象基础数据结构
文章图片
继承体系图
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。我也是一边理解一边写的。

    推荐阅读