IOSRuntime

Objective-C中Runtime的结构

2017-02-11  本文已影响0人  成博

Objective-C isa 指针 与 runtime 机制 这篇文章中详述了OC中Runtime的结构,附下图,

每个 类 都有一对儿objc_class结构体:存储实例相关内容的结构体和存储类相关内容的结构体(meta),

方便起见姑且把前者称之为Oclass,后者称之为Mclass吧,Oclass中的isa指向Mclass

这里只是简单介绍下就不多做赘述,重点要说的是Instance of class的结构,也算是对那篇文章的一个补充,

那篇文章中介绍了OC中Runtime结构组成,但没有说明创建实例时的结构和实例变量存储在哪里,

如上图,创建一个实例时,只创建一个Instance(objc_object结构体),然后其中isa指针指向系统中唯一的一对儿objc_class,但是我们可以看到objc_object结构体中只有一个isa指针,那么它的实例变量存储在那里呢?下面会详细介绍

下面是源码中的objc_class该结构体:

struct objc_class {

Class isa  OBJC_ISA_AVAILABILITY;

Class super_class                                        OBJC2_UNAVAILABLE;

const char *name                                        OBJC2_UNAVAILABLE;

long version                                            OBJC2_UNAVAILABLE;

long info                                                OBJC2_UNAVAILABLE;

long instance_size                                      OBJC2_UNAVAILABLE;

struct objc_ivar_list *ivars                            OBJC2_UNAVAILABLE;

struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;

struct objc_cache *cache                                OBJC2_UNAVAILABLE;

struct objc_protocol_list *protocols                    OBJC2_UNAVAILABLE;

} OBJC2_UNAVAILABLE;

每alloc一个实例的时候,会生成一个objc_object结构体如下,其中isa指向Oclass,Object就是一个objc_object

struct objc_object {

Class isa  OBJC_ISA_AVAILABILITY;

};

所有的实例方法地址都存储在Oclass的methodLists中,类方法地址在Mclass的methodLists中,调用实例内容就是在Oclass中寻径,调用类内容则在Mclass中寻径。

现在要说最关键的了:实例所拥有的变量存储在哪里呢?(这个问题官档没细说,其它介绍Runtime的文章也没提)

因为每个类在运行时只存在唯一一对儿Oclass和Mclass,可以看到objc_class中有个ivars,好像是存这里,但是实例变量是每个实例自有的啊!难道所有的objc_object的的实例变量都存在系统当中唯一的Oclass中吗?这是不合理的,讲道理的话实例变量应该存在objc_object当中才对,但是objc_object中只有一个isa指针,并没有地方去存变量。

源码里可以发现,ivars中存的是一个叫偏移量的东西,这个偏移量记载了实例变量存储的位置相对于objc_object的偏移量。所以获取实例变量的过程就是,先通过objc_object的isa指针找到Oclass,然后获取ivars中该实例变量存储位置相对于objc_object存储地址的偏移量,然后沿着objc_object的地址偏移个位置找到该实例。

这样的结构就解决了唯一一对儿objc-class对应无数个objc-object的问题。

但同样带了的缺陷就是开创一个objc-object时,就要对它在内存中的布局安排好,为它后面的实例变量预留空间,如果这个实例的某些变量压根儿没用到,即使不被赋值,它依旧占用着空间。(不知道apple有没有对这个做一些类似内存映射的技巧优化解决这个问题)。

上一篇下一篇

猜你喜欢

热点阅读