OC类的结构分析

根据苹果官网给的关系图做了一些验证

isa流程图.png

1.查看同一个类在内存中的个数

    Class class1 = [HTPerson class];
    Class class2 = [HTPerson alloc].class;
    Class class3 = object_getClass([HTPerson alloc]);
    Class class4 = [HTPerson alloc].class;
    
    NSLog(@"\n%p-\n%p-\n%p-\n%p",class1,class2,class3,class4);
复制代码

输出了如下的结果。证明同一个类在内存中,只会创建一个地址。

0x100004990-   
0x100004990-   
0x100004990-   
0x100004990   
复制代码

2.查询类的isa地址指向

    // NSObject实例对象
    NSObject *object1 = [NSObject alloc];
    // NSObject类
    Class class = object_getClass(object1);
    // NSObject元类
    Class metaClass = object_getClass(class);
    // NSObject根元类
    Class rootMetaClass = object_getClass(metaClass);
    // NSObject根根元类
    Class rootRootMetaClass = object_getClass(rootMetaClass);
    
    NSLog(@"\n%p 实例对象\n%p 类\n%p 元类\n%p 根元类\n%p 根根元类",object1,class,metaClass,rootMetaClass,rootRootMetaClass);
复制代码

输入了如下结果:

3B9E699C-0D46-4A9D-8DDC-007D9BBDA8A1.png

得出结论:

  • 实例对象的isa –> 类,
  • 类的isa –> 元类,
  • 元类对象isa –> 根元类
  • 根元类isa –> 根元类

3.类的继承关系

根据图中的继承关系(类-父类-父父类-null)做了如下验证:

    Class nSuperClass = class_getSuperclass(NSObject.class);//NSObject元类的父类
    
    NSLog(@"HTTeacher-类地址%p",HTTeacher.class);
    NSLog(@"HTPerson-父类地址%p",HTPerson.class);
    NSLog(@"NSObject-父父类地址%p",NSObject.class);
    NSLog(@"NSObjectSuper-父父父类%@ -- 父父父类%p",nSuperClass,nSuperClass);
复制代码
2021-06-20 18:34:30.592061+0800 002-isa分析[16955:397181] HTTeacher-类地址0x100008b40
2021-06-20 18:34:30.592425+0800 002-isa分析[16955:397181] HTPerson-父类地址0x100008af0
2021-06-20 18:34:30.592493+0800 002-isa分析[16955:397181] NSObject-父父类地址0x7fff94a3f118
2021-06-20 18:34:30.592555+0800 002-isa分析[16955:397181] NSObjectSuper-父父父类(null) -- 父父父类0x0
复制代码
  • HTPerson 继承于 NSObject,NSObject继承于nil

4.类的内部结构

在源码objc.h中,可以看到 typedef struct objc_class *Class。class属于objc_class的指针类型。
搜索 objc_class 可以找到如下三个成员:

struct objc_class : objc_object {
    ...
    // Class ISA;              //指向元类    8字节
    Class superclass;          //父类       8字节
    cache_t cache;             //缓存 结构体 16字节
    class_data_bits_t bits;    //对象方法和属性
    ...
   }
复制代码

查看 class_data_bits_t

struct class_data_bits_t {
   ...
     class_rw_t* data() const {
       return (class_rw_t *)(bits & FAST_DATA_MASK);
   }
   ...
}
复制代码

查看 class_rw_t里面有以下几个方法。

struct class_rw_t {
    //方法列表
    const method_array_t methods() const {...}
    //属性列表
    const property_array_t properties() const {...}
    //代理方法
    const protocol_array_t protocols() const {...}
}

复制代码

根据内存地址中的存储内容进行验证:(使用到了内存地址平移

@interface LGPerson : NSObject{
    NSString *subject;
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *hobby;

- (void)sayNB;
+ (void)say666;
复制代码

获取下面的输出结果:(x/4gx打印类的内存。p/x打印地址)

0F080F0D-155E-42BB-B6BD-14E995D2761F.png

截屏2021-06-20 下午7.55.53.png
输出方法列表类似操作即可:

截屏2021-06-20 下午7.59.41.png

总结

类中有主要有isasuperclasscachebits成员变量,bits中存储属性列表、方法列表、成员变量列表、协议列表等.

搞完了,出去运动下。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享