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
我们可以在类中找到实例对象的方法,也就是我们,在元类中找到类对象方法,也就是我们用到的+号方法。