本文由快学吧个人写作,以任何形式转载请标明原文出处。

一、为什么要了解isa

isa是oc的一个非常重要的内容,一切的继承联系中都存在isa的身影,isa存储了非常多的有用信息,在继承,初始化,内存的分配上都有着重要的效果。

二、探究思路

1、找到isa的源码。

2、检查isa的实质。

3、检查isa相关的代码。

三、查找isa源码

需求的材料 : objc4-818.2 : github.com/LGCooci/KCO…

适配的环境是macos11.1,更高的版本的在上面的链接中也有可编译的源码。

1、初见isa是从alloc的源码剖析中找到的,所以持续找alloc的源码。

2、打开818.2,在xcode的Navigator中查找alloc {,找到alloc的源码。

3、进入源码完成 : alloc –> _objc_rootAlloc –> call_alloc –> _objc_rootAllocWithZone –> _class_createInstanceFromZone

4、榜首篇文章中已经知道了isa的初始化会调用的是 : obj->initIsa(cls)

四、浅谈isa

5、进入obj->initIsa(cls),然后持续进入initIsa(cls,false,false)方法的完成。

四、浅谈isa

6、找到isa。看方法最后的赋值 : isa = newisa;所以能够推断,newisa便是一个实例化的isa。

四、浅谈isa

四、浅谈isa

7、看newisa的类型isa_t

四、浅谈isa

四、isa的实质

从上一点能够看出,isa的实质是一个联合体,联合体的概念在这儿。

四、浅谈isa

1、isa结构简单剖析

isa源码能够看第(三)节中的第7点中的图。

(1) isa的结构函数

isa有两个结构函数 :

四、浅谈isa

第二个结构函数 : isa_t(uintptr_t value) : bits(value) { }是C++结构函数和初始化的组合写法,:后面是给成员bits赋值,参数便是小括号里边的value

(2) isa的成员

isa有三个结构体成员,分别是 : uintptr_t bits;Class cls和一个结构体。由于isa是一个联合体,所以cls和bits和结构体是不可能同时被赋值的。

四、浅谈isa

bits和cls先不说,直接看isa结构体中的结构体成员,这是一个匿名的结构体。能够看到呈现这个结构体成员的前提是宏界说了ISA_BITFIELD。所以全局查找ISA_BITFIELD

ISA_BITFIELD的源码图片。

四、浅谈isa

四、浅谈isa

四、浅谈isa

四、浅谈isa

从源码能够看出来,差别是在不同的处理器架构下,ISA_BITFIELD的宏界说内容不同。我们主要用的便是x86_64的就行。

所以看ISA_BITFIELD源码图片中的第三张图。

isa的匿名结构体是一个位域,里边的内容具体如下 :

nonpointer : 表明是否对isa敞开指针优化,1表明敞开,那么isa中就包含了类信息、目标的引证计数等。0则表明纯isa指针,只保留了指向类的地址。
has_assoc  相关目标标志位。1表明有,0表明没有。
has_cxx_dtor : 该目标是否有c++或许objc的析构器。1表明有,那么就需求做析构逻辑,0表明没有,那么目标就能够更快的开释。
shiftcls : 存储类指针的值。
magic  : 用于调试器来判断当时的目标是真的目标,还是只是一个没有初始化的空间。
weakly_referenced : 表明目标是否被指向或许从前指向过一个ARC的弱变量。没有弱引证的目标能够更快的开释。
unused : 原来叫deallocating,现在改名字了。表明目标是否正在开释内存。
has_sidetable_rc : 当目标的引证计数大于10的时候,则需求借用该变量存储进位。
extra_rc : 表明引证计数的值,实践是引证计数的值-1。
关于extra_rc和has_sidetable_rc举例  假如目标的引证计数值为10,那么extra_rc就为9。假如引证计数值大于10,则使用has_sidetable_rc。

关于nonpointer,经常能够看到nonpointer,他的意思是非指针。假如为1,那么就证明这个目标的isa是一个不纯洁的isa,它的一些信息会存储到上面的结构体里边,假如为0,证明是一个纯洁的isa,那么isa存储的就只有cls,也便是一个指向父类的指针信息。

可是isa不是只能是nonponiter或许不是,指针的值也是能够存进上面的这个结构体中的。

五、isa的初始化

isa的初始化还是从alloc那里进入,和上面的第三节第4点里的相同,找到obj->initIsa(cls),进入initIsa。能够看到 :

四、浅谈isa

持续进入initIsa。会发现这是一个objc_object的函数。所以应该全局查找void initIsa( :

四、浅谈isa

objc_object是目标的实质,这儿先不说,先看初始化isa,一共有4个对isa的初始化函数。每一个都全局查找一下,会发现它们最后全部都是完成initIsa函数。所以只需求看initIsa函数就够了。下图为initIsa函数的源码完成。

四、浅谈isa

能够看到isa的结构体成员的赋值,都是在这儿完成的。