本文由快学吧个人写作,以任何形式转载请表明原文出处。
一、资料准备
objc4-818.2 : github.com/LGCooci/KCO…
对应mac的版本是11.1。可根据自己的系统版本挑选可以进行调试的源码。
二、探索思路
1、创建一个对象,获取这个对象的类
2、利用clang,将源码编译。
3、查看编译后的类。
4、找到类的数据结构。
5、在源码内进行一层一层的剖析。
三、创建项目
创建一个自定义的类,继承于NSObject。在818.2的main.m中创建这个类的实例对象,然后用Class获取这个实例对象的类信息。用Class的原因是oc中所有的类都可以用Class来接收。所以具有普遍性。
从terminal终端进入项目所在的文件夹,进入到main.m所在的文件夹下,然后用clang进行编译,clang命令 : clang -rewrite-objc main.m -o main.cpp
。
在生成的main.cpp文件中查找自定义的类,例如我自定义的JDPerson,会发现JDPerson是一个objc_object结构体。
再看Class是什么结构。查找Class,硬找太困难,所以找规律,看JDPerson,发现一个类被编译后,可以发现它的本质的地方,都有一种格式 : "类 + ;"。
所以搜索Class;
,一共49个,很好找,Class的本质也是结构体,是objc_class结构体,如下图 :
所以普通的继承类的本质是objc_object,而Class编译后的本质是objc_class。这是在这里得到的一个信息。
四、源码探索类的本质
源码中查找objc_class :
可以得到的信息是 :
- objc_class是一个继承于objc_object的结构体
- objc_class有四个成员,但是成员ISA被注释。
为什么ISA成员被注释?但是还要放在代码里面,其实是相当于占位,告诉看到这里的人,这里是应该有一个ISA的。既然子类没有,那么ISA就应该是继承于父类的,所以查找objc_object的源码,如下 :
找到了ISA。从上述源码,可以得到的信息是,所谓的万物皆对象,就是万物皆objc_object。一切类的源头,就是objc_object。
而我们常说的万物皆NSObject,和这里是否有冲突?查看NSObject的定义,在源码中找到NSObject.h文件 :
可以看到NSObject的定义和objc_object的结构是完全一样的,也就是说,NSObject是objc_object的一种仿写。objc_object是编译后的结构,NSObject是编译前的定义,所以万物皆NSObject也是没有问题的,并不冲突。
五、为什么isa是Class类型
-
万物皆对象,isa也是对象,也可以由Class接收。
-
从isa的来源来看,源码中搜索Class isa,找到isa的来源如下 :
- 找getIsa() :
- ISA()源码 :
- getDecodedClass源码 :
- getClass源码 :
从6中的图可以看到,返回的类型,会被强转为Class。也可以说明为什么isa是Class类型的。
六、总结
- Class(类)的本质是objc_class
- objc_class是继承于objc_object的结构体
- 由上述两点可以得出,类的本质是objc_object。并且可以得出,万物皆对象。
- NSObject是OC仿写的objc_object,所以万物是NSObject与万物是objc_object是不冲突的。
- 类的结构体中有四个重要的成员,分别是isa(继承于objc_object),superclass(父类),cache(缓存),bits(数据)。