前言
面向对象 + 内存管理. + runtime总结 后续随时补充,总结为主,省略了一些源码实现
面向对象
1.1 一个NSObject对象占用多少内存?
参考:MJ-iOS底层原理总结】一个NSObject对象占用多少内存?
在编译器中查看,有两种查看Size的方法
方式一:class_getInstanceSize([NSObject class])
方式二:malloc_size((__bridge const void *)(obj))
// 一个NSObject对象占用多少内存
- (void)testObj {
NSObject *obj = [[NSObject alloc] init];
NSLog(@"class_getInstanceSize = %zu", class_getInstanceSize([NSObject class]));
NSLog(@"malloc_size = %zu", malloc_size((__bridge const void *)(obj)));
/*
*/
}
class_getInstanceSize([NSObject class])
的意思是:获得NSObject实例对象的成员变量所占用的大小 ,并非获取NSObject所占用的大小。
malloc_size((__bridge const void *)(obj))
的意思是:获得obj指针所指向内存的大小。
结论:所以一个NSObject
对象占用16个字节,而真正利用起来的只有8个字节。系统分配了16个字节给NSObject对象(通过malloc_size函数获得),但NSObject
对象内部只使用了8个字节的空间
原理:OC底层在分配的时候判断一个对象至少分配6个字节,小于16字节强制分配6字节给这个对象。
1.2 iOS的继承链 & 对象的指针指向了哪里?
继承链分为类的继承链,元类的继承链和isa指针的指向三部分来学习。
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// NSLog(@"类继承探究:");
// [self testSuperClass:Stu.class];
// [self testSuperClass:Person.class];
// [self testSuperClass:NSObject.class];
//
NSLog(@"元类继承探究:");
[self testMetaClass:Stu.class];
[self testMetaClass:Person.class];
[self testMetaClass:NSObject.class];
}
// 元类继承链
/*
元类是系统自动创建的,和关联类同名。
对象的isa指向类,类对象的isa指向元类
*/
-(void)testMetaClass: (id) class {
Class cls = class;
Class metaClass = object_getClass(cls);
NSLog(@"类:%@_%p",cls,cls);
NSLog(@"元类:%@_%p",metaClass,metaClass);
[self testSuperClass:metaClass];
// 观察打印结果知道,父类的元类 = 元类的父类(根类NSObject除外)
// 根元类的父类 = 根类
}
// 继承链
- (void)testSuperClass:(id) class {
Class cls = class;
Class superClass = class_getSuperclass(cls);
Class rootSuperClass = class_getSuperclass(superClass);
NSLog(@"类:%@_%p",cls,cls);
NSLog(@"父类:%@_%p",superClass,superClass);
NSLog(@"父类:%@_%p",rootSuperClass,rootSuperClass);
NSLog(@"----------");
}
@end
元类继承链重点总结:
1. 元类是系统自动创建的,和关联类同名。
2. 对象的isa指向类,类对象的isa指向元类
3. 元类的父类 == 父类的元类(根类除外)
3. 根元类的父类 == 根类本身。
isa指针的指向总结:
- 对象的isa指向类
- 类的isa指向元类
- 元类的isa指向根元类
- 根元类的isa指向根元类
-(void) testSuperIsa:(id) obj {
Class isa = object_getClass(obj);
Class metaIsa = object_getClass(isa);
Class rootMetaIsa = object_getClass(metaIsa);
NSLog(@"对象:%@_%p",obj,obj);
NSLog(@"对象的isa-->%@_%p",isa,isa);
NSLog(@"类的isa-->%@_%p",metaIsa,metaIsa);
NSLog(@"元类isa-->%@_%p",rootMetaIsa,rootMetaIsa);
NSLog(@"----------");
}
- 下图能为上面的总结
1.3 OC的类的信息存放在哪里?-isa指针
在 Objective-C 中,每个对象都有一个 isa 指针,指向它的类对象。isa 指针实际上是一个指向一个 Class 结构体的指针,这个结构体包含了与类相关的一些信息。
- 类的名字;
- 父类的指针;
- 类的成员变量列表;
- 类的属性列表;
- 类的方法列表;
- 类的协议列表。
类对象在内存中有且仅有一个对象 主要包括 isa指针 super Class指针 类的属性信息 类的对象方法信息 类的协议信息 类的成员变量信息
类对象的isa指针有
// Class ISA;
Class superclass;
cache_t cache; // 方法缓存 formerly cache pointer and vtable
class_data_bits_t bits; // 用于获取具体的类信息 class_rw_t * plus custom rr/alloc flagsflags
...
bits
里面存储了类的方法列表等等信息ÿ