文章

Runtime01 类与元类

来看一张经典的描述 isasuperclass 指向的图。

从这我们可以看到:

isa

  • instance的isa指向class
  • class的isa指向meta-class
  • meta-class的isa指向基类的meta-class

superclass

  • class的superclass指向父类的class 如果没有父类,superclass指针为nil
  • meta-class的superclass指向父类的meta-class 基类的meta-class的superclass指向基类的class

方法调用

  • instance调用对象方法的轨迹 isa找到class,方法不存在,就通过superclass找父类
  • class调用类方法的轨迹 isa找meta-class,方法不存在,就通过superclass找父类

下面通过代码来确定一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@interface Person: NSObject
@end
...

void test1() {
    NSLog(@"NSObject class:%p metaclass:%p", [NSObject class], object_getClass([NSObject class]));

    Person *person = [[Person alloc] init];
    Class cls = person;
    int i = 0;
    while (i < 4) {
        NSLog(@"class:%p metaclass:%p", cls, object_getClass(cls));
        cls = object_getClass(cls);
        i++;
    }

}

输出信息:

NSObject class:0x7fff991bd118 metaclass:0x7fff991bd0f0
---> 说明 NSObject 的isa 确实指向它的元类

class:0x100659b60 metaclass:0x100002100
---> 说明 person对象的 isa 指向 Person类对象

class:0x100002100 metaclass:0x1000020d8
---> 说明 Peson类对象的 isa 指向 Person元对象

class:0x1000020d8 metaclass:0x7fff991bd0f0
---> 说明 Peson元类对象的 isa 指向 NSObject元类对象

class:0x7fff991bd0f0 metaclass:0x7fff991bd0f0
---> 说明 NSObject元类对象 isa 指向 NSObject元类对象

// 注:
// object_getClass 获取 isa 指向对象
Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}

我们再看一下 objc_allocateClassPair 方法内部实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes)
{
    Class cls, meta;

    rwlock_writer_t lock(runtimeLock);

    // Fail if the class name is in use.
    // Fail if the superclass isn't kosher.
    if (getClass(name)  ||  !verifySuperclass(superclass, true/*rootOK*/)) {
        return nil;
    }

    // Allocate new classes.
    cls  = alloc_class_for_subclass(superclass, extraBytes); //分配
    meta = alloc_class_for_subclass(superclass, extraBytes);

    // fixme mangle the name if it looks swift-y?
    objc_initializeClassPair_internal(superclass, name, cls, meta);

    return cls;
}

static void objc_initializeClassPair_internal(Class superclass, const char *name, Class cls, Class meta)
{
    runtimeLock.assertWriting();

    class_ro_t *cls_ro_w, *meta_ro_w;

    // 初始化cls和meta的大小和数据
    cls->setData((class_rw_t *)calloc(sizeof(class_rw_t), 1));
    meta->setData((class_rw_t *)calloc(sizeof(class_rw_t), 1));

    ...

    cls_ro_w->flags = 0; // 普通类
    meta_ro_w->flags = RO_META; // 标记为meta

    ...

    // Connect to superclasses and metaclasses
    cls->initClassIsa(meta); // 将cls的isa指向meta
    if (superclass) {
        meta->initClassIsa(superclass->ISA()->ISA()); // meta的isa指向根类的meta
        cls->superclass = superclass;
        meta->superclass = superclass->ISA(); //// meta的父类为父类的meta
        addSubclass(superclass, cls);
        addSubclass(superclass->ISA(), meta);
    } else {
        meta->initClassIsa(meta); // 根类的isa指向自己
        cls->superclass = Nil;
        meta->superclass = cls; // 根类的父类指向cls
        addRootClass(cls);
        addSubclass(cls, meta);
    }

    ....
}

本文由作者按照 CC BY 4.0 进行授权