面试题答案
一键面试动态类在内存中的布局
- 类对象:动态创建的类在内存中有一个类对象,它包含了类的元数据,例如类名、超类指针(指向
NSObject
)、实例变量列表、方法列表等。这个类对象在内存中是唯一的,并且在运行时动态分配内存。 - 实例对象:当通过这个动态类创建实例时,每个实例对象会分配内存来存储其实例变量。实例对象的内存布局首先是一个指向类对象的指针(isa指针),用于标识该实例属于哪个类,之后是按顺序排列的实例变量。
重写父类方法及处理方式
- 动态方法解析:在动态创建类时,可以通过
class_addMethod
函数来添加方法。如果要重写父类的方法,首先需要确保方法的签名(包括方法名、参数类型和返回值类型)与父类中要重写的方法一致。例如,假设父类NSObject
有一个-(void)description
方法,要重写这个方法,可以如下操作:
// 动态创建类
Class myClass = objc_allocateClassPair([NSObject class], "MyDynamicClass", 0);
// 定义重写方法的实现
void myDescription(id self, SEL _cmd) {
NSLog(@"This is my custom description");
}
// 添加重写的方法
class_addMethod(myClass, @selector(description), (IMP)myDescription, "v@:");
// 注册类
objc_registerClassPair(myClass);
- 消息转发:如果在动态创建类时没有及时添加重写方法,运行时会启动消息转发机制。首先会进行动态方法解析,尝试动态添加方法;如果失败则进入备用接收者查找;若还是失败,则进入完整的消息转发流程,包括方法签名的动态获取和最终的
forwardInvocation:
方法处理。在动态创建类过程中,正确添加重写方法可以避免复杂的消息转发流程,保证方法调用的准确性。 - 内存管理:在重写方法中,如果涉及到内存管理(例如对象的创建和释放),要遵循 Objective - C 的内存管理规则(ARC 或手动引用计数)。在 ARC 环境下,编译器会自动处理对象的内存管理;在手动引用计数环境下,需要在适当的地方调用
retain
、release
和autorelease
方法来保证内存的正确管理。例如,在重写的方法中创建一个新对象并返回时,在手动引用计数下需要确保返回对象的引用计数正确:
id myCustomMethod() {
id obj = [[MyObject alloc] init];
return [obj autorelease];
}
这样可以保证在方法调用完成后,对象的内存能够得到正确释放,避免内存泄漏。