面试题答案
一键面试ARC与runtime协同工作原理
- 对象引用计数管理
- ARC(自动引用计数)依赖runtime中的引用计数机制。在runtime底层,每个对象都有一个与之关联的引用计数。当对象创建时,引用计数初始化为1。例如,在ARC环境下创建一个NSObject对象:
NSObject *obj = [[NSObject alloc] init]; // 此时obj的引用计数为1
- 当对象被持有,如赋值给另一个变量时,runtime会自动增加引用计数。例如:
NSObject *obj1 = obj; // 此时obj和obj1指向同一个对象,该对象引用计数加1,变为2
- 当对象不再被引用,例如变量超出作用域,ARC借助runtime自动减少引用计数。比如:
{ NSObject *localObj = [[NSObject alloc] init]; } // localObj超出作用域,runtime自动减少该对象的引用计数,当引用计数降为0时,对象被释放
- isa指针与内存管理
- 每个对象都有一个isa指针,它指向对象的类。在ARC环境下,isa指针除了用于对象的类型识别外,也间接参与内存管理。runtime通过isa指针找到对象所属的类,类的元数据中包含了对象的内存布局等信息,这些信息对于正确管理对象内存至关重要。
- 例如,对于一个自定义类:
@interface MyClass : NSObject @property (nonatomic, strong) NSString *name; @end @implementation MyClass @synthesize name; @end
- 当创建MyClass对象时,runtime根据类的元数据确定对象的内存布局,包括为
name
属性分配内存。ARC通过isa指针找到MyClass类,了解其内存布局,从而正确管理对象及其属性的内存。当MyClass对象的引用计数降为0,runtime会根据类的元数据中定义的析构函数(如果有),先释放name
属性的内存,然后再释放MyClass对象本身的内存。
- autorelease池
- ARC同样依赖runtime中的autorelease池机制。在非ARC环境下,开发者需要手动创建和管理autorelease池,而在ARC环境下,编译器会自动插入合适的autorelease池代码。
- 例如,在一个循环中创建大量临时对象:
for (int i = 0; i < 1000; i++) { NSString *str = [NSString stringWithFormat:@"%d", i]; // 在ARC下,编译器会自动在合适位置插入autorelease池代码, // 当autorelease池被销毁时,池中的对象(如这里的str)引用计数会减1 }
- runtime会管理autorelease池的生命周期,当autorelease池被销毁时,池中的对象引用计数减少,有助于及时释放不再使用的对象内存,避免内存峰值过高。
ARC通过runtime的引用计数、类元数据以及autorelease池等特性,实现了高效且自动的对象内存管理。