iOS运行时中isa指针的本质

2020-03-08  本文已影响0人  MiniCoder

在OC中,因为类也是一个对象,所以也必须是另外一个类的实例,这个类就是元类(metaclass)。元类保存了类方法的列表。当一个类方法被调用的时候,元类会首先查找他本身是否有该方法的实现,如果没有,则元类会向他的父类查找方法,这样就可以一直找到继承链的头。
元类也是一个对象,元类的isa指针又指向哪里呢?为了设计的完整性,所有的元类的isa指针都会指向一个根元类。根元类的isa指针又会指向他自己,这样就形成了一个闭环


1981114-5036d6de4e94ce44.png

Class是一个指向objc_class(类)结构体的指针,而id是一个指向objc_object(对象)结构体的指针。
objc_object(对象)中isa指针指向的类结构称为objc_class(该对象的类),objc_class存放着普通成员变量与对象方法 (“-”开头的方法)。
objc_class(类)中isa指针指向的类结构称为metaclass(该类的元类),其中存放着static类型的成员变量与static类型的方法 (“+”开头的方法)。

从这里可以知道,OC的类其实也是一个对象,一个对象就要有一个它属于的类,意味着类也要有一个 isa 指针,指向他所属的类。那么元类的类是什么?就是我们所说的元类 (MetaClass) ,所以,元类就是类所属的类。从消息机制的层面来说:

当你给对象发送消息时,消息是在寻找这个对象的类的方法列表 。
当你给类发消息时,消息是在寻找这个类的元类的方法列表。
下面通过代码我们可以看一下详细的指向过程

   Person *p = [Person new];
    Class cls = object_getClass(p);
    //metaClass
    Class metaCls1 = object_getClass(cls);
    Class metaCls2 = object_getClass(metaCls1);
    Class metaCls3 = object_getClass(metaCls2);
    Class metaCls4 = object_getClass(metaCls3);
    Class class =  metaCls4;
    NSLog(@"实例 = %p ,类对象 =  %p,元类=  %p,根元类=  %p,根元类=  %p",p,cls,metaCls1,metaCls2,metaCls3);

实例 = 0x6000001a2440 ,类对象 =  0x107541bb8,元类=  0x107541be0,根元类=  0x7fff89e06698,根元类=  0x7fff89e06698

我们可以在类中找到实例对象的方法,也就是我们,在元类中找到类对象方法,也就是我们用到的+号方法。

上一篇下一篇

猜你喜欢

热点阅读