面试题答案
一键面试循环引用导致的问题
在Objective-C内存管理中,这种循环引用会导致内存泄漏。因为对象之间相互持有,引用计数不会降为0,即使这些对象不再被外部其他对象引用,它们所占用的内存也无法被释放。
检测循环引用
- 静态分析工具:Xcode自带的静态分析工具(Analyze)可以检测部分明显的循环引用。它通过静态分析代码逻辑,尝试找出可能存在的循环引用情况。
- ** Instruments工具 - 僵尸对象检测**:使用 Instruments 的 Zombies 模板。在程序运行时,如果对象已经被释放但仍被访问,Zombies 工具会捕获到这类问题,从而间接提示可能存在循环引用。
解决循环引用
- 使用弱引用(weak):对于这种循环引用关系,可以将其中一端的引用设置为 weak,以打破循环。
// 假设这是对象A的类定义 @interface ClassA : NSObject @property (nonatomic, strong) ClassB *objectB; @end @implementation ClassA @end // 对象B的类定义 @interface ClassB : NSObject @property (nonatomic, strong) ClassC *objectC; @end @implementation ClassB @end // 对象C的类定义 @interface ClassC : NSObject @property (nonatomic, weak) ClassA *objectA; // 使用weak打破循环引用 @end @implementation ClassC @end
- 使用无主引用(unowned):无主引用和弱引用类似,也是不增加对象的引用计数。但无主引用在被引用对象释放后不会自动置为nil,使用时需确保被引用对象在使用期间不会被释放。
// 假设这是对象A的类定义 @interface ClassA : NSObject @property (nonatomic, strong) ClassB *objectB; @end @implementation ClassA @end // 对象B的类定义 @interface ClassB : NSObject @property (nonatomic, strong) ClassC *objectC; @end @implementation ClassB @end // 对象C的类定义 @interface ClassC : NSObject @property (nonatomic, unowned) ClassA *objectA; // 使用unowned打破循环引用 @end @implementation ClassC @end
一般来说,当可以确定被引用对象的生命周期至少和引用对象一样长时,使用无主引用;否则使用弱引用。