类的结构分析

433 阅读3分钟
  • 准备工作

定义两个类TDPersonTDTeacher然后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

  • 先看类在底层到底是什么

    1. 先将main.m编译成.cpp文件结果
    struct TDTeacher_IMPL {
    	struct TDPerson_IMPL TDPerson_IVARS;
    };
    
    struct TDPerson_IMPL {
    	struct NSObject_IMPL NSObject_IVARS;
    };
    
    struct NSObject_IMPL {
    	Class isa;
    };
    
    从.cpp文件就可以看出每个对象里面都会有一个isa指针,而且可以得到isa的类型是class
    1. 再去源码里面看Class到底是什么
    typedef struct objc_class *Class;
    
    发现Class其实就是objc_class类型的指针
    1. 继续探索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的走位
    1. 先看对象中isa的指向从打印结果很清楚的验证了对象里面的isa指向创建她的类
    2. 再看类里面isa的指向 看到这里可能会有点疑问了 po 0x0000000100002258 & 0x00007ffffffffff8ULL又是TDTeacher,原因是:
      1. 第一步打印出的TDTeacher是objc2的类
      2. 第一步po 0x0000000100002258 & 0x00007ffffffffff8ULL打印出的TDTeacher类的类,在Apple中叫做元类,所以两个打印都是TDTeacher
      元类说明:
      • 我们都知道 对象的isa 是指向类,类的其实也是一个对象,可以称为类对象,其isa的位域指向苹果定义的元类
      • 元类是系统给的,其定义和创建都是由编译器完成,在这个过程中,类的归属来自于元类
      • 元类本身是没有名称的,由于与类相关联,所以使用了同类名一样的名称
    3. 再看元类中isa走位 发现元类的isa指向NSObject
    4. 继续往下走看NSObject里面的isa的指向发现NSObject中的isa又指向了自己
    5. 根类实例化的对象isa走位
    6. 根据isa走位得出的结论
      • 对象isa => 自己的类, 类的isa => 元类, 元类isa => 根元类, 根元类isa => 自己
      • 父类实例化对象isa => 父类, 父类isa => 元类, 元类isa => 根元类, 根元类isa => 自己
      • 根类实例化的对象isa => 根类,根类isa => 根元类,根元类isa => 自己
  • 分析类中的superclass走向

根据上文中的的类的结构源码可知第一个参数是类的isa,第二个参数是superclass

  1. 类的superclass走向
  2. 元类superclass走向
  • 根据上文的走向分析得出金典的isa走位&继承关系图

  • 探索类信息中的内容

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits; 
    ...  //下面的方法省略
}
  1. isa属性:继承自objc_object的isa,占8字节,指向类信息
  2. superclass 属性:Class类型,Class是由objc_object定义的,是一个指针,占8字节,指向父类
  3. cache属性:简单从类型class_data_bits_t目前无法得知,而class_data_bits_t是一个结构体类型,结构体的内存大小需要根据内部的属性来确定,而结构体指针才是8字节,缓存