一、oc对象底层原理分析

2019-04-03  本文已影响0人  iOS_进击的小学生

一、OC对象的分类

OC对象主要可以分为三种:
instance对象(实例对象)
class对象(类对象)
meta-class对象(元类对象)

1.instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象。object1和object2都是NSObject的instace对象(实例对象),但他们是不同的两个对象,并且分别占据着两块不同的内存。
NSObjcet *object1 = [[NSObjcet alloc] init];
NSObjcet *object2 = [[NSObjcet alloc] init];

instance对象在内存中存储的信息包括:1.isa指针 2.其他成员变量。


image.png

那么一个NSObject对象占用多少内存?
NSObjcet实际上是只有一个名为isa的指针的结构体,因此占用一个指针变量所占用的内存空间大小,如果64bit占用8个字节,如果32bit占用4个字节。

2.每一个类在内存中有且只有一个class对象。可以通过打印内存地址证明
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = [NSObject class];
// runtime
Class objectClass4 = object_getClass(object1);
Class objectClass5 = object_getClass(object2);
NSLog(@"%p %p %p %p %p", objectClass1, objectClass2, objectClass3, objectClass4, objectClass5);

class对象在内存中存储的信息主要包括:
isa指针
superclass指针
类的属性信息(@property),类的成员变量信息(ivar)
类的对象方法信息(instance method),类的协议信息(protocol)


image.png
成员变量的值时存储在实例对象中的,因为只有当我们创建实例对象的时候才为成员变赋值。但是成员变量叫什么名字,是什么类型,只需要有一份就可以了。所以存储在class对象中。
3.元类对象 meta-class
//runtime中传入类对象此时得到的就是元类对象
Class objectMetaClass = object_getClass([NSObject class]);
// 而调用类对象的class方法时得到还是类对象,无论调用多少次都是类对象
Class cls = [[NSObject class] class];
Class objectClass3 = [NSObject class];
class_isMetaClass(objectMetaClass) // 判断该对象是否为元类对象
NSLog(@"%p %p %p", objectMetaClass, objectClass3, cls); // 后面两个地址相同,
说明多次调用class得到的还是类对象
每个类在内存中有且只有一个meta-class对象。

meta-class对象和class对象的内存结构是一样的,但是用途不一样,在内存中存储的信息主要包括:
isa指针
superclass指针
类的类方法的信息(class method)

meta-class对象和class对象的内存结构是一样的,所以meta-class中也有类的属性信息,类的对象方法信息等成员变量,但是其中的值可能是空的。
image.png

二、对象的isa指针指向哪里

1.instance的isa指向class,当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用。
2.class的isa指向meta-class
当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用


image.png

3.当对象调用其父类对象方法的时候,又是怎么找到父类对象方法的呢?,此时就需要使用到class类对象superclass指针。

当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用,同样如果Person发现自己没有响应的对象方法,又会通过Person的superclass指针找到NSObject的class对象,去寻找响应的方法
image.png

4.当类对象调用父类的类方法时,就需要先通过isa指针找到meta-class,然后通过superclass去寻找响应的方法。

当Student的class要调用Person的类方法时,会先通过isa找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用。

最后又是这张静定的isa指向图,经过上面的分析我们在来看这张图,就显得清晰明了很多。


image.png
对isa、superclass总结

1.instance的isa指向class
2.class的isa指向meta-class
3.meta-class的isa指向基类的meta-class,基类的isa指向自己
4.class的superclass指向父类的class,如果没有父类,superclass指针为nil
5.meta-class的superclass指向父类的meta-class,基类的meta-class的superclass指向基类的class
6.instance调用对象方法的轨迹,isa找到class,方法不存在,就通过superclass找父类
7.class调用类方法的轨迹,isa找meta-class,方法不存在,就通过superclass找父类
本文面试题总结:

一个NSObject对象占用多少内存?

答:一个指针变量所占用的大小(64bit占8个字节,32bit占4个字节)
对象的isa指针指向哪里?
答:instance对象的isa指针指向class对象,class对象的isa指针指向meta-class对象,meta-class对象的isa指针指向基类的meta-class对象,基类自己的isa指针也指向自己。
OC的类信息存放在哪里?
答:成员变量的具体值存放在instance对象。对象方法,协议,属性,成员变量信息存放在class对象。类方法信息存放在meta-class对象。

参考链接:https://www.jianshu.com/p/aa7ccadeca88

上一篇下一篇

猜你喜欢

热点阅读