-
准备工作
定义两个类TDPerson和TDTeacher然后TDTeacher继承TDPerson,这两个类里面的内容分别是
TDPerson:
#import "TDPerson.h"
@interface TDPerson(){
NSString * _name;
}
@property(nonatomic, copy) NSString * avatar;
-(void)run;
+(void)say;
@end
@implementation TDPerson
-(void)run{
}
+(void)say{
}
@end
TDTeacher:
#import "TDTeacher.h"
@interface TDTeacher()
@end
@implementation TDTeacher
@end
-
先看类在底层到底是什么
- 先将main.m编译成.cpp文件结果
从.cpp文件就可以看出每个对象里面都会有一个isa指针,而且可以得到isa的类型是classstruct TDTeacher_IMPL { struct TDPerson_IMPL TDPerson_IVARS; }; struct TDPerson_IMPL { struct NSObject_IMPL NSObject_IVARS; }; struct NSObject_IMPL { Class isa; };- 再去源码里面看Class到底是什么
发现Class其实就是objc_class类型的指针typedef struct objc_class *Class;- 继续探索objc_class这个结构体的内容
发现objc_class继承自objc_object,objc_object里面有个参数isa同样也是class类型,这里就验证了一句话类也被称为类对象,类其实也是一个对象也有isa指向它的类,同时这里还有一个很常见的面试题objc_object 与 对象的关系从上面的源码就可以看出所有的对象都是按照objc_class这个结构体的模板创建出来的而objc_class又是继承objc_object的所以objc_object 与 对象的关系是继承
-
先通过lldb命令探索isa走位
通过上文可知对象类都有一个参数isa(算是废话,应为上文已经验证类其实也是对象),接下来看下isa的走位- 先看对象中isa的指向
从打印结果很清楚的验证了对象里面的isa指向创建她的类
- 再看类里面isa的指向
看到这里可能会有点疑问了 po 0x0000000100002258 & 0x00007ffffffffff8ULL又是TDTeacher,原因是:
- 第一步打印出的TDTeacher是objc2的类
- 第一步po 0x0000000100002258 & 0x00007ffffffffff8ULL打印出的TDTeacher类的类,在Apple中叫做元类,所以两个打印都是TDTeacher,
- 我们都知道 对象的isa 是指向类,类的其实也是一个对象,可以称为类对象,其isa的位域指向苹果定义的元类
- 元类是系统给的,其定义和创建都是由编译器完成,在这个过程中,类的归属来自于元类
- 元类本身是没有名称的,由于与类相关联,所以使用了同类名一样的名称
- 再看元类中isa走位
发现元类的isa指向NSObject
- 继续往下走看NSObject里面的isa的指向
发现NSObject中的isa又指向了自己
- 根类实例化的对象isa走位
- 根据isa走位得出的结论
- 对象isa => 自己的类, 类的isa => 元类, 元类isa => 根元类, 根元类isa => 自己
- 父类实例化对象isa => 父类, 父类isa => 元类, 元类isa => 根元类, 根元类isa => 自己
- 根类实例化的对象isa => 根类,根类isa => 根元类,根元类isa => 自己
- 先看对象中isa的指向
-
分析类中的superclass走向
根据上文中的的类的结构源码可知第一个参数是类的isa,第二个参数是superclass
- 类的superclass走向
- 元类superclass走向
-
根据上文的走向分析得出金典的isa走位&继承关系图
-
探索类信息中的内容
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits;
... //下面的方法省略
}
- isa属性:继承自objc_object的isa,占8字节,指向类信息
- superclass 属性:Class类型,Class是由objc_object定义的,是一个指针,占8字节,指向父类
- cache属性:简单从类型class_data_bits_t目前无法得知,而class_data_bits_t是一个结构体类型,结构体的内存大小需要根据内部的属性来确定,而结构体指针才是8字节,缓存