iOS基础·OC高级篇iOS精英班iOS 开发

iOS RunTime之二:数据结构

2016-09-19  本文已影响590人  s_在路上

由上面一章中,我们了解了什么是RunTimeRunTime用来做什么,下面了解一下Runtime数据结构。

我们知道在Objective-C中,使用[object doSomething]语法并不会马上执行object接受者对象的doSomething方法的代码,而是向object接受者对发送一条doSomething消息,这条消息可能由object接受者对来处理,也可能由转发给其他对象来处理,也有可能假装没有接收到这条消息而没有处理。

其实[object doSomething]被编译器转化为:

id objc_msgSend ( id self, SEL op, ... );

下面从两个数据结构idSEL来逐步分析和理解Runtime有哪些重要的数据结构。

id

objc_msgSend方法里面的第一个参数的数据类型id,通用类型指针,能够表示任何对象。

Paste_Image.png

查看源文件,可以看出id其实就是一个指向objc_object结构体指针,它包含一个Class isa成员,根据Class isa指针就可以找到对象所属的类。

Class

从源文件看出,Objective-C的对象就是一个包含isa指针的数据结构,而isa指针的数据类型是ClassClass表示对象所属的类。

Paste_Image.png

从源文件看出,Class其实就是一个objc_class结构体指针。objc_class结构体定义如下:

isa:在Objective-C中,所有的类自身也是一个对象,即类对象。在这个类对象里面也有一个isa指针,它指向metaClass(元类)。
super_class:指向该类的父类,如果该类已经是最顶层的根类(如NSObject),则super_class为NULL。
name:这个类的类名。
version:提供类的版本信息,这对于对象的序列化非常有用,它可是让我们识别出不同类定义版本中实例变量布局的改变。
info:类信息,供运行期使用的一些位标识。
instance_size:该类的实例变量大小。
ivars:该类的成员变量链表。
methodLists:方法定义的链表。
protocols:协议链表。
cache:一个接收者对象接收到一个消息时,它会根据isa指针去查找能够响应这个消息的对象。在实际使用中,这个对象只有一部分方法是常用的,很多方法其实很少用或者根本用不上。这种情况下,如果每次消息来时,我们都是methodLists中遍历一遍,性能势必很差。这时,cache就派上用场了。在我们每次调用过一个方法后,这个方法就会被缓存到cache列表中,下次调用的时候runtime就会优先去cache中查找,如果cache没有,才去methodLists中查找方法。这样,对于那些经常用到的方法的调用,但提高了调用的效率。

注意:

元类(Meta Class)

Objective-C中,所有的类自身也是一个对象,这个对象里面也有一个isa指针,它指向metaClass(元类),向这个对象发送消息(即调用类方法)。

Paste_Image.png

从图中看出:

Objective-C的设计者让所有的meta-class的isa指向基类的meta-class,以此作为它们的所属类。即,任何NSObject继承体系下的meta-class都使用NSObject的meta-class作为自己的所属类,而基类的meta-class的isa指针是指向它自己,这样就形成了一个完美的闭环。

SEL

objc_msgSend函数第二个参数类型为SEL,它是selectorObjc中的表示类型(Swift中是Selector类)。selector是方法选择器,可以理解为区分方法的id,而这个id的数据结构是SEL,即表示一个方法的selector的指针。

Paste_Image.png

IMP

IMP实际上是一个函数指针,指向方法实现的首地址。其定义如下:

id (*IMP)(id, SEL, ...)

第一个参数是指向 self 的指针(如果是实例方法,则是类实例的内存地址;如果是类方法,则是指向元类的指针),第二个参数是方法选择器( selector ),接下来是方法的实际参数列表。

SEL就是为了查找方法的最终实现IMP的,由于每个方法对应唯一的SEL,因此我们可以通过SEL方便快速准确地获得它所对应的IMP

Method

Method是一种代表类中的某个方法的类型。

Paste_Image.png

objc_method在上面的方法列表中提到过,它存储了方法名,方法类型和方法实现:

Paste_Image.png

注意:

Ivar

Ivar是一种代表类中实例变量的类型。

Paste_Image.png Paste_Image.png

Cache

Paste_Image.png

Cache其实就是一个存储Method的链表,主要是为了优化方法调用的性能。

当对象receiver调用方法message时,首先根据对象receiverisa指针查找到它对应的类,然后在类的methodLists中搜索方法,如果没有找到,就使用super_class指针到父类中的methodLists查找,一旦找到就调用方法。如果没有找到,有可能消息转发,也可能忽略它。但这样查找方式效率太低,因为往往一个类大概只有20%的方法经常被调用,占总调用次数的80%。所以使用Cache来缓存经常调用的方法,当调用方法时,优先在Cache查找,如果没有找到,再到methodLists查找。

上一篇 下一篇

猜你喜欢

热点阅读