1. OC对象的底层实现?
Objective-C的面向对象都是基于C/C++的数据结构实现的,接下来我们来探究一下OC对象的底层实现;
1.1 NSObject的底层实现
首先在main函数里面定义一个obj对象:
int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... NSLog(@"Hello, World!"); NSObject *obj = [[NSObject alloc] init]; } return 0; }
将main.m转换为c++代码,通过如下命令:
xcrun -sdk iphoneos clang -arch arm64 -F Foundation.framework -rewrite-objc main.m -o main.cpp
查看main.cpp文件,会发现这样一个结构体:
struct NSObject_IMPL { Class isa; };
我们查看NSObject对象的声明:
@interface NSObject <NSObject> { Class isa OBJC_ISA_AVAILABILITY; }
通过对比我们会发现一个NSObject对象实际上就是一个结构体,通过objc的源码看到Class的定义如下,实际上它就是一个指向结构体的指针,故isa是一个指针类型;
typedef struct objc_class *Class;
1.2 自定义对象的底层实现
我们定义一个对象
@interface Person : NSObject { @public int age; int height; } @end @implementation Person @end
通过1.1中的命令,再来看一下它的底层实现:
struct Person_IMPL { struct NSObject_IMPL NSObject_IVARS; int age; int height; };
而NSObject_IMPL的实现如下:
struct NSObject_IMPL { Class isa; };
则Person的最终实现可以理解为:
struct Person_IMPL { Class isa; int age; int height; };
使用如下代码验证一下p所指向的对象就是Person_IMPL这个结构体,从打印结果可以看出确实如此
int main(int argc, const char * argv[]) { @autoreleasepool { Person *p = [[Person alloc] init]; p->age = 4; p->height = 10; struct Person_IMPL *p_imp = (__bridge struct Person_IMPL *)(p); NSLog(@"%d", p_imp->age);//打印结果:4 } return 0; }
1.3 自定义对象的嵌套底层实现
@interface Person : NSObject { @public int age; } @end @implementation Person @end @interface Student : Person { @public int height; } @end @implementation Student @end
通过1.1中的命令,再来看一下它的底层实现:
struct NSObject_IMPL { Class isa; }; struct Person_IMPL { struct NSObject_IMPL NSObject_IVARS; int age; }; struct Student_IMPL { struct Person_IMPL Person_IVARS; int height; };
而Student最终可以理解为
struct Student_IMPL { Class isa; int age; int height; };
2. alloc源码解读
2.1 创建一个Person对象,其中Person类中无任何成员变量
2.2 进入到alloc方法的源码实现中
2.3 跳转到_objc_rootAlloc函数中
2.4 callAlloc实现
hasCustomAWZ为是否实现了allocWithZone方法
// class or superclass has default alloc/allocWithZone: implementation // Note this is is stored in the metaclass. #define FAST_CACHE_HAS_DEFAULT_AWZ (1<<14) bool hasCustomAWZ() const { return !cache.getBit(FAST_CACHE_HAS_DEFAULT_AWZ); }
2.5 执行_objc_rootAllocWithZone方法
2.6 执行_class_createInstanceFromZone方法
先看size = cls->instanceSize(extraBytes),其中extraBytes为0,这里执行到了cache.fastInstanceSize(extraBytes),如果走到了下面会看到如果分配的size小于16的话,size会强制设置为16
接着看fastInstanceSize之后会执行到align16函数,16字节对齐算法,会发现size就是为16;
实际上类所分配的实际内存最低都为16的倍数,这一点是从操作系统的层面去考虑的,为了加快cpu的读写速度,另一方面,也为了避免数据错乱,如果感兴趣的可以下载libmalloc源码自行查看;
接下来会调用calloc以及isa的处理等,这里不再深入分析,至此整个alloc流程结束;
3. init源码解读
调用init方法(实例方法的init)接着会来到下方,然后整个流程结束
我们会发现整个流程什么都没做,苹果这样设计的目的是什么呢?实际上这是苹果的一种设计模式就是为了将来我们在使用的时候,可以在重写init的内部做一些自定义的操作;
- (instancetype)init { if (self = [super init]) { //... } return self; }
4. new源码解读
调用new的时候,会发现内部调用了callAlloc又调用了init函数,会发现又来到了callAlloc函数,接下来的整个过程和alloc过程一致,实际上调用new就相当于调用了alloc - init函数;
线