面试题答案
一键面试__block关键字与ARC机制协同工作及原理
- 对象引用计数变化:在ARC环境下,使用
__block
修饰的变量,如果其类型是对象类型,它会对对象进行强引用。当__block
变量指向对象时,对象的引用计数会增加。例如:
__block NSObject *obj = [[NSObject alloc] init];
// 此时obj对NSObject对象有强引用,对象引用计数加1
当__block
变量生命周期结束或者重新赋值为nil
时,对象引用计数会相应减少。
2. runtime层操作:在runtime层,__block
变量会被包装成一个结构体。这个结构体内部会包含指向所引用对象的指针。当在block内部访问__block
变量时,实际上是通过这个结构体来访问的。例如,当block捕获__block
变量时,runtime会处理结构体的内存管理,确保在block执行期间,__block
变量所引用的对象不会被提前释放。
3. 编译器优化:编译器会对__block
变量的访问进行优化。在编译期,编译器会生成特定的代码来处理__block
变量的引用和释放逻辑。例如,在block内部对__block
变量的赋值操作,编译器会生成代码来正确调整对象的引用计数。同时,编译器会确保__block
变量在不同作用域之间的传递和使用是符合内存管理规则的。
__weak关键字与ARC机制协同工作及原理
- 对象引用计数变化:
__weak
关键字用于创建一个弱引用。弱引用不会增加对象的引用计数。例如:
NSObject *strongObj = [[NSObject alloc] init];
__weak NSObject *weakObj = strongObj;
// weakObj对strongObj所指向的对象没有增加引用计数
当对象的强引用计数降为0并被释放时,所有指向该对象的__weak
指针会自动被设置为nil
,即所谓的“零弱引用”特性。
2. runtime层操作:runtime维护了一个弱引用表,用于记录所有的弱引用关系。当对象即将被释放时,runtime会遍历这个弱引用表,将所有指向该对象的__weak
指针置为nil
。这个过程涉及到runtime对对象生命周期的监控以及对弱引用表的操作。例如,当对象的引用计数变为0时,runtime会调用objc_destructInstance
函数,在这个函数中会处理弱引用的归零操作。
3. 编译器优化:编译器在处理__weak
变量时,会生成代码来确保在使用__weak
变量时,首先检查其是否为nil
,以避免野指针访问。同时,编译器会协助runtime正确地管理弱引用关系,例如在对象的内存布局中预留空间来存储弱引用信息,以便runtime能够高效地处理弱引用的添加和移除操作。