iOS底层原理

Objective-C对象的本质

2020-09-16  本文已影响0人  爱看书de图图

  我们知道平时编写的OC代码,底层都是CC++代码:Objective-C -> C/C++ -> 汇编语言 -> 机器语言。所以Objective-C对象的底层实现就是CC++
  那么请思考问题:Objective-C对象,是基于C/C++什么类型的数据结构实现的?
  答案大家都知道,结构体。因为结构体可以存放不同的数据类型。想要看清OC的底层实现,我们可以使用下面①的命令行。但是编译后我们会发现,一个简单的文件就会编译出超过10万行的代码,这是因为clang在编译时候,是有不同的平台区分的,比如Windows平台,Mac平台。所以我们可以使用②的命令指定平台,这样代码就会简化很多。

1、clang -rewrite-objc main.m -o main.cpp
2、xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp

  我们可以看找到一个类对象的实现,NSObject_IMPLNSObject implementation

struct NSObject_IMPL {
    Class isa;
};

  然后我们在定义一个类Student然后继续执行上面的命令,看看在底层转化是否是结构体如下所示。这里是Student_IMPL结构体的第一个成员变量就是NSObject。这样的好处就是我定义的Student类里拥有NSObject的所有属性。

struct Student_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
};

下面有个问题,为什么NSObjectisaClass类型的,通过之前的iOS开发之alloc和init分析,我们查看方法initInstanceIsa,我们可以看到isa的类型是isa_t(如下图isa_t),在底层进行了强转,类似于swift中的as,可以查看源码(如下图强转)。

isa_t 强转
总结:

1.OC的本质是结构体
2.子类的isa继承自父类

isa_t的类型
isa_t
  在这里我们看到了一个关键词union(共用体/联合体),构造数据类型的方式,有两种:

1、结构体(struct)。
2、联合体(union,或者叫共用体)。

结构体
结构体是指把不同的数据组合成一个整体,其变量是共存的,变量不管是否使用,都会分配内存。

联合体
联合体也是由不同的数据类型组成,但其变量是互斥的,所有的成员共占一段内存。而且共用体采用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会将原来成员的值覆盖掉

两者的区别
内存占用情况

内存分配大小

1.nonpointer

2.has_assoc表示是否有关联对象。
3.has_cxx_dtor表示该对象是否有C++/OC的析构函数。

4.shiftclx表示存储类信息。arm64架构下33位,x86_64架构下占44位。
5.magic用于调试器判断当前对象是真的对象还是没有初始化的空间,占6位。
6.weakly_refrenced,是否被弱引用,没有可以更快释放。
7.deallocating表示对象是否正在释放内存。
8.has_sidetable_rc表示当对象引用计数大于10时,则需要借用该变量存储进位。
9.extra_rc(额外的引用计数) --- 导尿管表示该对象的引用计数值,实际上是引用计数值减1。如果对象的引用计数是10,那么extra_rc为9.

验证isa指针位域信息(0-64) image.png

  上方的nonpointertrue,所以走下面的方法,进入第一个断点,我们进行lldb调试,返现newisa信息都为空,继续往下走,当走到newisa.bits = ISA_MAGIC_VALUE; define ISA_MAGIC_VALUE 0x001d800000000001ULL后,我们在进行调试(如下图)


  和上面的信息比较,我们得到了cls = 0x001d800000000001,在计算器中打开(如下图)   我们发现从47位开始是111011,然后我们把计算器转换成10进制,输入magic = 59(如下图),同样的也是111011,在47号位置的值就是59。有没有感觉到很神奇,666!!!
  所以calloc的意义和我们之前文章里讲述的就一模一样了,是把isa和我们的类,关联起来。newisa.shiftcls = (uintptr_t)cls >> 3;,我们来进一步验证这行代码。经过赋值之后,我们看到newisashiftcls被赋值成功了,注意,我们上面是没有shiftcls的。右移三位是为了不覆盖原来的前三个位置的信息(nonpointer,has_assoc,has_cxx_dtor
上一篇 下一篇

猜你喜欢

热点阅读