OC源码分析之对象的创建
2023-12-28 16:30:30
深入剖析OC对象的创建过程
在Objective-C中,对象是程序的基本构建单元,对象的创建是程序运行过程中的一项重要任务。对象是如何创建的?底层发生了什么?本文将从Objective-C的源码角度,对对象的创建过程进行详细分析,揭示alloc和init这两个关键方法的底层实现,帮助读者更深入地理解Objective-C内存管理机制的本质。
alloc源码解析:揭秘内存分配过程
Objective-C中的对象是通过alloc方法来创建的,alloc方法负责分配对象的内存空间。alloc方法的源码位于苹果官方开源代码库中的objc4源码文件中,路径为iOS_os_objc/runtime/objc-runtime-new.m。
alloc方法的实现很简单,它首先检查对象是否已经存在,如果存在,则直接返回对象的指针。否则,它会调用objc_allocateClassPair方法来分配一个新的对象。objc_allocateClassPair方法的实现如下:
Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes)
{
size_t instanceSize = class_getInstanceSize(superclass);
size_t totalSize = instanceSize + extraBytes;
Class newClass = (Class)calloc(1, totalSize);
newClass->isa = superclass;
return newClass;
}
objc_allocateClassPair方法首先计算新对象的大小,然后调用calloc函数分配内存空间。calloc函数会将分配的内存空间初始化为0,这有助于防止出现野指针。接下来,将新对象的isa指针指向父类,这表明新对象继承自父类。最后,将新对象返回。
init源码分析:探究对象初始化过程
alloc方法分配了对象的内存空间,但并没有对对象进行初始化。对象的初始化需要通过调用init方法来完成。init方法的源码位于苹果官方开源代码库中的objc4源码文件中,路径为iOS_os_objc/runtime/objc-runtime-new.m。
init方法的实现也比较简单,它首先检查对象是否已经初始化,如果已经初始化,则直接返回对象的指针。否则,它会调用objc_msgSendSuper方法来调用父类的init方法。objc_msgSendSuper方法的实现如下:
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
{
struct objc_class *class = super->receiver->class;
IMP imp = class->superclass->vtable[op - class->superclass->method_list->method_start];
return (*imp)(super->receiver, op, ...);
}
objc_msgSendSuper方法首先找到对象的父类,然后在父类的虚方法表中找到要调用的方法。最后,调用该方法,并返回方法的返回值。
在init方法中,objc_msgSendSuper方法被用来调用父类的init方法。这确保了子类对象在初始化时,父类的init方法也会被调用。
实例解析:对象创建的具体过程
为了更好地理解对象的创建过程,我们来看一个具体的例子。假设我们要创建一个名为Person的类,该类有一个名为name的属性。
@interface Person : NSObject
{
NSString *name;
}
- (instancetype)init;
@end
@implementation Person
- (instancetype)init
{
self = [super init];
if (self) {
name = [[NSString alloc] initWithString:@"John Doe"];
}
return self;
}
@end
当我们调用[[Person alloc] init]来创建一个Person对象时,首先会调用alloc方法来分配内存空间。alloc方法会调用objc_allocateClassPair方法来分配一个新的对象,并将其isa指针指向Person类。
接下来,会调用init方法来初始化对象。init方法会调用objc_msgSendSuper方法来调用父类的init方法。父类的init方法会将对象的isa指针指向NSObject类,并初始化对象的属性。
在子类的init方法中,会调用[[NSString alloc] initWithString:@"John Doe"]来创建一个NSString对象,并将其赋值给name属性。
最后,init方法会返回self,并将其赋值给Person对象。这样,一个新的Person对象就被创建出来了。
总结
通过对alloc和init这两个关键方法的源码分析,我们揭示了Objective-C中对象创建的底层实现。我们了解到,alloc方法负责分配对象的内存空间,而init方法负责初始化对象。
理解了对象创建的底层实现,有助于我们更深入地理解Objective-C内存管理机制的本质。同时,这也有助于我们编写出更高质量的Objective-C代码。