04.ISA与Class

本文基于 objc4-818.2 源码

本文较长,建议吃饱喝足再进行阅读。由于很多内容关联性很强,本来准备拆分一下的。但还是决定放在一起,逐步深入。避免发生 这里一个知识点在另一篇文章,那我晚点再看(根本不会再看) 的情况。

其中 协议列表 的探究过程中遇到了一些问题,无法进行下去,有解决办法的欢迎交流~

一、类对象

在上一文中我们初步探究了,obj和isa.

通过下面的步骤我们可以找到类对象

(lldb) p/x obj1
(RYObject *) $8 = 0x000000028026c340
(lldb) x/4gx 0x000000028026c340
0x28026c340: 0x000001a1042194f1 0x0000000000000000
0x28026c350: 0x0000b6106e0ac350 0x000000028356012e
(lldb) p/x 0x000001a1042194f1 & 0x0000000ffffffff8ULL
(unsigned long long) $14 = 0x00000001042194f0
(lldb) po 0x000001a1042194f1 & 0x0000000ffffffff8ULL
RYObject

1.1 类对象ISA

Class其实也是一个对象,那么我很好奇。类对象是不是也有个ISA呢?

我们以同样的步骤进行调试:

(lldb) p/x 0x000001a1042194f1 & 0x0000000ffffffff8ULL
(unsigned long long) $11 = 0x00000001042194f0
(lldb) x/4gx 0x00000001042194f0
0x1042194f0: 0x00000001042194c8 0x00000001fc942218
0x104219500: 0x00030002815641c0 0x0003801000000000
(lldb) po 0x00000001042194c8
RYObject

居然也有一个RYObject,并且内存地址和第一步生成的0x00000001042194f0 不一样,是0x00000001042194c8

这里的0x00000001042194c8其实就是元类

二、元类

我们将刚才编译过的MachO丢进MachoView中解析。

打开符号表,搜索RYObject

  • _OBJC_METACLASS_RO$_RYObject

    • 元类

  • _OBJC_CLASS_RO$_RYObject

三、ISA与Class的关系

我们使用下面的代码进行验证,其中RYSubObject继承RYObject

    RYObject *rySubObject = [[RYSubObject alloc] init];
    NSLog(@"实例%@ 的地址是 %p", rySubObject, rySubObject);
    Class rySubObjectClass = object_getClass(rySubObject);
    NSLog(@"实例%@ 的类对象是 %@ 地址是 %p", rySubObject, rySubObjectClass, rySubObjectClass);
    Class rySubObjectMetaClass = object_getClass(rySubObjectClass);
    NSLog(@"实例%@ 的元类是 %@ 地址是 %p", rySubObject, rySubObjectMetaClass, rySubObjectMetaClass);
    Class rySubObjectRootMetaClass = object_getClass(rySubObjectMetaClass);
    NSLog(@"实例%@ 的根元类是 %@ 地址是 %p", rySubObject, rySubObjectRootMetaClass, rySubObjectRootMetaClass);

    NSLog(@"\n");

    RYObject *ryObject = [[RYObject alloc] init];
    NSLog(@"实例%@ 的地址是 %p", ryObject, ryObject);
    Class ryObjectClass = object_getClass(ryObject);
    NSLog(@"实例%@ 的类对象是 %@ 地址是 %p", ryObject, ryObjectClass, ryObjectClass);
    Class ryObjectMetaClass = object_getClass(ryObjectClass);
    NSLog(@"实例%@ 的元类是 %@ 地址是 %p", ryObject, ryObjectMetaClass, ryObjectMetaClass);
    Class ryObjectRootMetaClass = object_getClass(ryObjectMetaClass);
    NSLog(@"实例%@ 的根元类是 %@ 地址是 %p", ryObject, ryObjectRootMetaClass, ryObjectRootMetaClass);

    NSLog(@"\n");

    NSObject *nsObject = [[NSObject alloc] init];
    NSLog(@"实例%@ 的地址是 %p", nsObject, nsObject);
    Class nsObjectClass = object_getClass(nsObject);
    NSLog(@"实例%@ 的类对象是 %@ 地址是 %p", nsObject, nsObjectClass, nsObjectClass);
    Class nsObjectMetaClass = object_getClass(nsObjectClass);
    NSLog(@"实例%@ 的元类是 %@ 地址是 %p", nsObject, nsObjectMetaClass, nsObjectMetaClass);
    Class nsObjectRootMetaClass = object_getClass(nsObjectMetaClass);
    NSLog(@"实例%@ 的根元类是 %@ 地址是 %p", nsObject, nsObjectRootMetaClass, nsObjectRootMetaClass);

    NSLog(@"\n");

    Class rySubSuperClass = class_getSuperclass(rySubObjectClass);
    NSLog(@"子类%@(地址%p)的父类是%@ 地址是%p",rySubObjectClass,rySubObjectClass, rySubSuperClass, rySubSuperClass);
    Class rySuperClass = class_getSuperclass(ryObjectClass);
    NSLog(@"父类%@(地址%p)的父类是%@ 地址是%p",ryObjectClass,ryObjectClass, rySuperClass, rySuperClass);
    Class nsSuperClass = class_getSuperclass(nsObjectClass);
    NSLog(@"根类%@(地址%p)的父类是%@ 地址是%p",nsObjectClass,nsObjectClass, nsSuperClass, nsSuperClass);

    NSLog(@"\n");

    Class rySubMetaSuperClass = class_getSuperclass(rySubObjectMetaClass);
    NSLog(@"元类%@(地址%p)的父类是%@ 地址是%p",rySubObjectMetaClass,rySubObjectMetaClass, rySubMetaSuperClass, rySubMetaSuperClass);
    Class ryMetaSuperClass = class_getSuperclass(ryObjectMetaClass);
    NSLog(@"元类%@(地址%p)的父类是%@ 地址是%p",ryObjectMetaClass,ryObjectMetaClass, ryMetaSuperClass, ryMetaSuperClass);
    Class nsMetaSuperClass = class_getSuperclass(nsObjectMetaClass);
    NSLog(@"根元类%@(地址%p)的父类是%@ 地址是%p",nsObjectMetaClass,nsObjectMetaClass, nsMetaSuperClass, nsMetaSuperClass);

依次得到输出如下

3.1 子类ISA

2021-06-22 21:21:53.685253+0800 Class[15467:5499656] 实例<RYSubObject: 0x282af0700> 的地址是 0x282af0700
2021-06-22 21:21:53.685426+0800 Class[15467:5499656] 实例<RYSubObject: 0x282af0700> 的类对象是 RYSubObject 地址是 0x10227d648
2021-06-22 21:21:53.685717+0800 Class[15467:5499656] 实例<RYSubObject: 0x282af0700> 的元类是 RYSubObject 地址是 0x10227d620
2021-06-22 21:21:53.685782+0800 Class[15467:5499656] 实例<RYSubObject: 0x282af0700> 的根元类是 NSObject 地址是 0x1fc9421f0

子类实例对象 -isa- 子类 -isa- 子类元类 -isa- 根元类

3.2 父类ISA

2021-06-22 21:21:53.685876+0800 Class[15467:5499656] 实例<RYObject: 0x282afc490> 的地址是 0x282afc490
2021-06-22 21:21:53.685929+0800 Class[15467:5499656] 实例<RYObject: 0x282afc490> 的类对象是 RYObject 地址是 0x10227d5a8
2021-06-22 21:21:53.686703+0800 Class[15467:5499656] 实例<RYObject: 0x282afc490> 的元类是 RYObject 地址是 0x10227d580
2021-06-22 21:21:53.686760+0800 Class[15467:5499656] 实例<RYObject: 0x282afc490> 的根元类是 NSObject 地址是 0x1fc9421f0

实例对象 -isa--isa- 元类 -isa- 根元类

3.3 根类ISA

2021-06-22 21:21:53.687198+0800 Class[15467:5499656] 实例<NSObject: 0x282afdae0> 的地址是 0x282afdae0
2021-06-22 21:21:53.687245+0800 Class[15467:5499656] 实例<NSObject: 0x282afdae0> 的类对象是 NSObject 地址是 0x1fc942218
2021-06-22 21:21:53.687291+0800 Class[15467:5499656] 实例<NSObject: 0x282afdae0> 的元类是 NSObject 地址是 0x1fc9421f0
2021-06-22 21:21:53.687384+0800 Class[15467:5499656] 实例<NSObject: 0x282afdae0> 的根元类是 NSObject 地址是 0x1fc9421f0

根类实例对象 -isa- 根类 -isa- 根元类 -isa- 根元类

3.4 ISA关系图

我们将上面的三组关系整合一下

3.5 类继承关系

2021-06-22 21:21:53.687691+0800 Class[15467:5499656] 子类RYSubObject(地址0x10227d648)的父类是RYObject 地址是0x10227d5a8
2021-06-22 21:21:53.687822+0800 Class[15467:5499656] 父类RYObject(地址0x10227d5a8)的父类是NSObject 地址是0x1fc942218
2021-06-22 21:21:53.688283+0800 Class[15467:5499656] 根类NSObject(地址0x1fc942218)的父类是(null) 地址是0x0

子类 -继承- 父类 -继承- 根类 -继承-

3.6 元类继承关系

2021-06-22 21:21:53.688982+0800 Class[15467:5499656] 元类RYSubObject(地址0x10227d620)的父类是RYObject 地址是0x10227d580
2021-06-22 21:21:53.689029+0800 Class[15467:5499656] 元类RYObject(地址0x10227d580)的父类是NSObject 地址是0x1fc9421f0
2021-06-22 21:21:53.689075+0800 Class[15467:5499656] 根元类NSObject(地址0x1fc9421f0)的父类是NSObject 地址是0x1fc942218

这里发现 根元类NSObject(地址0x1fc9421f0) 的父类是 根类(地址0x1fc942218)

子类的元类 -继承- 父类的元类 -继承- 根元类 -继承- 根类

3.7 ISA与Class的继承关系图梳理

Last updated