探秘isa指针
我们都知道OC对象分为三类,分别是:
instance
对象(实例对象)
class
对象(类对象)
meta-class
对象(元类对象)
那这三类对象之间存在着某种联系呢?
instance
对象
instance
对象就是通过类alloc
出来的对象,每次调用alloc
都会产生新的instance
对像
`example`:
NSObject *obj1 = [[NSObject alloc] init];
NSObject *obj2 = [[NSObject alloc] init];
obj1
和 obj2
就是NSObject
的instance
对象,并且他们是两个不同的对象,分别占据了两块不同的内存,那么它们在内存中又如何分配的呢?我们可以通过clang
编译器将OC
代码转换成C\C++
语言
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的cpp文件
image.png
从而我们发现
Personal
对象里面包含NSObject_IMPL
和一些其他成员变量,关于NSObject_IMPL
在https://www.jianshu.com/p/73745a984209文章中已经赘述。
故
instance
对象对象里面包含isa
指针和一些其他成员变量
class
对象
class
对象可以通过[instance class]
获得,或者通过objc/runtime.h
中的object_getClass(id _Nullable obj)
获得
`example`:
Class *objClass1 = [obj1 class];
Class *objClass2 = [obj1 class];
Class *objClass3 = object_getClass(object1);
Class *objClass4 = object_getClass(object2);
objClass1 ~ objClass4
都是class
对象,并且他们都是同一个对象,每个类在内存中有且只有一个class
对象
我们通过objc
源码可知,Class
对象主要包括这些信息
image.png
image.png
故
class
对象对象里面包含isa
指针、superclass
指针、类的属性
信息、对象方法
、协议
以及成员变量
信息
meta-class
对象
meta-class
对象只能通过objc/runtime.h
中的object_getClass(id _Nullable obj)
获得,而不能通过[[instance class] class]
获得
`example`:
Class *objMetaClass = object_getClass([NSObject class]);
objMetaClass
是NSObject
的meta-class
对象,并且每个类中有且只有一个meta-class
对象
因为meta-class
对象和class
对象都是返回Class
对象,故他们的内存结构是相同的,但是它们的用途确实不一样的。
故
class
对象对象里面包含isa
指针、superclass
指针、类的类方法
信息....
我们都知道instance
对象调用的是实例方法(减方法)
,class
对象调用的是类方法(加方法)
,但是它们之间如何是联系起来的呢?
从上图我们看出
personan->isa
指针的地址指向的personClass2
的内存地址,而personClass2->isa
指针指向的是personMetaClass
的内存地址(注:从64bit开始,isa需要进行一次位运算,才能计算出真实地址
)
分析得知:
instance
的isa
指向class
,当调用对象方法时,通过instance
的isa
找到class
,最后找到对象方法的实现进行调用
class
的isa
指向meta-class
当调用类方法时,通过class
的isa
找到meta-class
,最后找到类方法的实现进行调用
因此我们可以通过下面这张图做个总结:
image.png
instance
的isa
指向class
class
的isa
指向meta-class
meta-class
的isa
指向基类的meta-class
class
的superclass
指向父类的class
如果没有父类,superclass
指针为nil
meta-class
的superclass
指向父类的meta-class
基类的meta-class
的superclass
指向基类的class