OC的对象 是基于C/C++的结构体实现的(因为结构体里面可以存放各种不同类型的数据)
如何查看cpp代码
1.找到你所需要传的文件的上一层文件夹 cd 到这个文件夹
2.clang -rewrite-objc main.m(你所需要转的文件名称) -o main.cpp(转成什么样的文件)
这种的是所有地方都可以运行的cpp文件 很大
3. xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的CPP文件 这种是指定平台
一个NSObject对象占用多少内存?
- 系统分配了16个字节给NSObject对象(通过malloc_size函数获得)
- 但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得)
NSObject *obj = [[NSObject alloc] init];
//获得NSObject类的实例对象的成员变量所占用的存储空间的大小
NSLog(@"%zd",class_getInstanceSize([NSObject class]));
//获得objc指针所指向内存的大小
NSLog(@"%zd",malloc_size((__bridge const void *)(obj)));
iOS是小端模式 从高地址开始读取数据
方法不存放在实例对象里面 实例对象存放他的成员变量
oc对象内存分配都是16的倍数
sizeof 不是函数 是一个运算符 在编译器编译的时候 就变成一个常数 在编译的时候就确定的 不需要开辟空间
创建一个实例对象,至少需要多少内存?
#import <objc/runtime.h>
class_getInstanceSize([NSObject class]);
创建一个实例对象,实际上分配了多少内存?
#import <malloc/malloc.h>
malloc_size((__bridge const void *)obj);
OC对象的分类
1.instance对象 (实例对象)
2.class对象 (类对象)
3.meta-class对象 (元类对象)
instance对象
instance对象就是通过类alloc出来的对象 每次调用alloc都会产生新的instance对象
instance对象在内存中存储的信息包括
1.isa指针
2.其他成员变量
class对象
每个类在内存中有且只有一个class对象
class方法返回的一直是class对象
NSObject *object1 = [[NSObject alloc] init];
Class objectClass = [object1 class];
Class objectClass2 = object_getClass(object1);
Class objectClass3 = [NSObject class];
class对象在内存中存储的信息包括
1.isa指针
2.superclass指针
3.类的属性信息(@property) 类的对象方法信息(instance method)
4.类的协议信息(protocol) 类的成员变量信息(ivar)
meta-class对象(元类对象)
meta-data 元数据 描述数据的数据
每个类在内存中有且只有一个meta-class对象
meta-class 对象 和 class 对象的内存结构是一样的 但是 用途不一样
//将类对象作为参数传入 获得元类对象
NSObject *object1 = [[NSObject alloc] init];
Class objectMetaClass = object_getClass([NSObject class]);
Class objectMetaClass1 = object_getClass([object1 class]);
meta-class对象在内存中存储的信息包括
1.isa指针
2.superclass指针
3.类的类方法信息(class method)
class_isMetaClass(objectMetaClass) 判断是否为元类对象
object_getClass 和 objc_getClass 的区别
object_getClass
1.如果传入实例对象 返回类对象
2.如果传入类对象 返回meta-class对象
3.如果传入meta-class对象 返回基类NSObject的meta-class对象
objc_getClass
传入类名(字符串) 返回对应的 类对象
-(Class) class 和 +(Class) class
返回类对象
对象方法的调用过程
- instance的isa指向class
当调用对象方法时 通过isa的找到class 最后找到对象方法的实现进行调用
- class的isa指向meta-class
当调用类方法时 通过class的isa找到meta-class 最后找到类方法的实现进行调用
class对象的superclass指针
当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到
Person的class,最后找到对象方法的实现进行调用
meta-class对象的superclass指针
当Student的class要调用Person的类方法时,会先通过isa找到Student的meta-class,然后通过superclass找到
Person的meta-class,最后找到类方法的实现进行调用
isa、superclass总结
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
instance调用对象方法的轨迹
isa找到class,方法不存在,就通过superclass找父类
class调用类方法的轨迹
isa找meta-class,方法不存在,就通过superclass找父类
流程图 .png
获取isa
MJPerson *person = [[MJPerson alloc] init];
p/x (long)person->isa
实例对象的isa & ISA_MASK 是类对象的地址值
类对象的isa & ISA_MASK 是元类对象的地址值
类对象superclass指针里面就是父类对象的地址值
对象的isa指针指向哪里?
- instance对象的isa指向class对象
- class对象的isa指向meta-class对象
- meta-class对象的isa指向基类的meta-clas对象
OC的类信息存放在哪里
- 对象方法 属性 成员变量 协议信息 存放在class对象中
- 类方法 存放在meta-class对象中
- 成员变量的具体值 存放在instance对象中
内存大小(64bit下).png
类对象和元类对象一直存放在内存中 只有一份
网友评论