Runtime01 类与元类
来看一张经典的描述 isa 和 superclass 指向的图。
从这我们可以看到:
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 进行授权
