iOS 底层探索篇 —— OC对象本质 & noPointerIsa
一. 对象的本质探索
Clang
clang是一个由Apple主导编写,基于LLVM的C/C++/OC的编译器
操作代码
实例
通过这个指令,就可以把main.m 编译成 main.cpp 文件,可以更好的观察底层的一些结构及实现的逻辑,方便理解底层原理。
对象的本质
对象在底层的本质是结构体,那么是如何得到这个结论的呢。
首先我们在main.m 文件中声明一个类LGPerson,有一个属性 NSString LSName(为了避免是巧合,取一个特殊的名字)。
然后我们按照上文中的方法将 main.m 编译成 main.cpp 文件,然后将main.cpp 文件打开,并且搜索一下我们的类LGPerson。
我们可以看到LGPerson 中有两个参数
第一个参数就是isa,是继承自NSObject_IMPL,属于伪继承,伪继承的方式是直接将NSObject_IMPL结构体定义为LGPerson中的第一个属性,意味着LGPerson 拥有 NSObject_IMPL中的所有成员变量。
第二个参数就是我们的成员变量 LSName。
同时我们注意到,在main.cpp中,LGPerson的本质类型是 objc_object,这是为什么呢?
这是因为LGPerson继承自NSObject, 而NSObject 在底层中的实现就是objc_object,因此LGPerson的本质类型是 objc_object。
Class类型的本质类型
我们在main.cpp中寻找,找到上图可知, 得出class 是 objc_class 的结构体指针。并且我们也可以得知为什么id 不加*, 因为底层中已经加过了。
getter 和 setter
继续在main.cpp 中寻找,我们找到
从名字以及参数中,我们大致可以看出这个是LGPerson 的getter 和setter 方法,但是这个参数我们从来没有见到过。这些参数是隐藏参数。
为什么return 是 self + objc_ivar 呢?因为我们需要拿到内存地址才能拿到内存的值,拿到person首地址,然后拿到ivar 空间平移的量进行平移,才能获得LSName所在的地址,拿到地址才能获取里面的值。
二. 联合体位域
在这个结构体中,存了四个bool值,每个bool值占一个字节,根据内存对齐原则,可以得出这个struct总共占了4个字节。
而用sizeof可以得出,这个struct真的是占用了4个字节。显然,bool 不是 0 就是1,实际上用4位去存就可以了,用四个字节去存有点浪费内存了。
位域
这里,我们可以用位域,来指定这个成员占多少位。举个