iOS 底层探索篇 —— OC对象本质 & noPointerIsa

iOS 底层探索篇 —— OC对象本质 & noPointerIsa

一. 对象的本质探索

Clang

clang是一个由Apple主导编写,基于LLVM的C/C++/OC的编译器

操作代码

iOS 底层探索篇 —— OC对象本质 & noPointerIsa

实例

iOS 底层探索篇 —— OC对象本质 & noPointerIsa
通过这个指令,就可以把main.m 编译成 main.cpp 文件,可以更好的观察底层的一些结构及实现的逻辑,方便理解底层原理。

对象的本质

对象在底层的本质是结构体,那么是如何得到这个结论的呢。
首先我们在main.m 文件中声明一个类LGPerson,有一个属性 NSString LSName(为了避免是巧合,取一个特殊的名字)。

iOS 底层探索篇 —— OC对象本质 & noPointerIsa
然后我们按照上文中的方法将 main.m 编译成 main.cpp 文件,然后将main.cpp 文件打开,并且搜索一下我们的类LGPerson。

iOS 底层探索篇 —— OC对象本质 & noPointerIsa

我们可以看到LGPerson 中有两个参数
第一个参数就是isa,是继承自NSObject_IMPL,属于伪继承,伪继承的方式是直接将NSObject_IMPL结构体定义为LGPerson中的第一个属性,意味着LGPerson 拥有 NSObject_IMPL中的所有成员变量。
第二个参数就是我们的成员变量 LSName。
iOS 底层探索篇 —— OC对象本质 & noPointerIsa
同时我们注意到,在main.cpp中,LGPerson的本质类型是 objc_object,这是为什么呢?
这是因为LGPerson继承自NSObject, 而NSObject 在底层中的实现就是objc_object,因此LGPerson的本质类型是 objc_object。
iOS 底层探索篇 —— OC对象本质 & noPointerIsa

Class类型的本质类型

iOS 底层探索篇 —— OC对象本质 & noPointerIsa
我们在main.cpp中寻找,找到上图可知, 得出class 是 objc_class 的结构体指针。并且我们也可以得知为什么id 不加*, 因为底层中已经加过了。

getter 和 setter

继续在main.cpp 中寻找,我们找到
iOS 底层探索篇 —— OC对象本质 & noPointerIsa
从名字以及参数中,我们大致可以看出这个是LGPerson 的getter 和setter 方法,但是这个参数我们从来没有见到过。这些参数是隐藏参数
为什么return 是 self + objc_ivar 呢?因为我们需要拿到内存地址才能拿到内存的值,拿到person首地址,然后拿到ivar 空间平移的量进行平移,才能获得LSName所在的地址,拿到地址才能获取里面的值。

二. 联合体位域

iOS 底层探索篇 —— OC对象本质 & noPointerIsa
在这个结构体中,存了四个bool值,每个bool值占一个字节,根据内存对齐原则,可以得出这个struct总共占了4个字节。

iOS 底层探索篇 —— OC对象本质 & noPointerIsa
而用sizeof可以得出,这个struct真的是占用了4个字节。显然,bool 不是 0 就是1,实际上用4位去存就可以了,用四个字节去存有点浪费内存了。

位域

这里,我们可以用位域,来指定这个成员占多少位。举个

上一篇:用ATL和MFC来创建ActiveX控件


下一篇:Angular4 后台管理系统搭建(10) - 做一个通用的可跨域上传文件的组件