首先看三个面试题,本片文章的核心。
1.一个NSObject对象占有多少内存?
2.对象的isa指针的指向哪里?
3.OC的类信息存放在哪里?
一.对象的大小
对象的本质其实是结构体,计算结构体大小(对象实际大小),因为内存对齐 ,8的倍数 class_getInstanceSize / sizeof
系统实际分配对象内存,内存对齐,16的倍数。malloc_size
NSLog(@"-------%zu",class_getInstanceSize([[NSObject alloc] class]));
NSLog(@"-------%zu",sizeof([[NSObject alloc] class]));
NSLog(@"-------%zu",malloc_size((__bridge const void *)([NSObject alloc])));
2021-02-25 17:31:36.444104+0800 Interview01-OC对象的本质[45350:1506255] -------8
2021-02-25 17:31:36.444380+0800 Interview01-OC对象的本质[45350:1506255] -------8
2021-02-25 17:31:36.444419+0800 Interview01-OC对象的本质[45350:1506255] -------16
内存对齐: 1. 实际分配内存大小为16的倍数 2.结构体实际占用内存大小必须是最大成员大小的倍数
二.对象的种类
Instance实例对象 (存储 isa指针与其他成员变量)
获取实例对象
// instance对象,实例对象
NSObject *object1 = [[NSObject alloc] init];
Class类对象(存储isa指针,superclass指针,类的属性信息(@property),类的对象方法信息(instance method),类的协议信息(protocol),类的成员变量信息(ivar))
获取类对象
// class对象,类对象
// class方法返回的一直是class对象,类对象
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = object_getClass(object1);
Class objectClass4 = object_getClass(object2);
Class objectClass5 = [NSObject class];
在源码中的结构关系为
meta-class元类对象(包含isa指针,superclass指针,类的类方法信息(class method),class_ismetaclass 用来判断是否为元类对象)
获取 meta-class对象,元类对象
// 将类对象当做参数传入,获得元类对象
Class objectMetaClass = object_getClass(objectClass5/*objectClass5 为类对象*/);
三.isa与superclass
首先,我们先放一张非常经典的图。
结合图片理解为:
isa的指向:对象的 isa 指向 类; 类的 isa 指向 元类,元类的 isa 指向 根元类(基类),根元类(基类)的 isa 指向 自己。
类的superclass的指向:类的 superclass 指向父类, 父类的 superclass 指向 根类 ,根类的superclass 指向 nil;
元类的superclass的指向:元类的 superclass 指向 父类的元类,父元类的 superclass 指向 根元类, 根元类的 superclass 指向 根类, 根类的 superclass 指向nil。
例1:
Person *p = [[Person alloc] init];
如何获取到对象P的isa指向的类:
class q == object_getClass(p)
根据对象P的isa指向类对象的isa获取到元类
object_getClass(q)
class_isMetaClass() //可以用来检测是否为元类
class_isMetaClass(object_getClass([Person class]))
例2
有如下图关系Student类与Person类
isa指针的指向关系
superclass指针指向关系为
student与person在总结图中的对象关系为
实例对象调用对象方法的流程
类对象调用类方法的流程
1.一个NSObject对象占有多少内存?
- 系统分配了16个字节给NSObject对象(通过malloc_size函数获得)
- 但是NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得)
2.对象的isa指针的指向哪里?
- instance对象的isa指向class对象
- class对象的isa指向meta-class对象
- meta-class对象的isa指向基类的meta-class对象
3.OC的类信息存放在哪里?
- 对象方法,属性,成员变量,协议信息,存放在class对象中
- 类方法存放在meta-class对象中
- 成员变量的具体值存放在instance对象中