MST
星途 面试题库

面试题:Objective-C内存管理中的循环引用问题

在Objective-C中,如何检测和解决循环引用问题?请举例说明,比如两个视图控制器之间相互持有对方,如何打破这种循环引用,并且阐述weak和strong关键字在解决循环引用时起到的作用。
25.3万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试
  1. 检测循环引用
    • 使用 Instruments
      • Instruments 是 Xcode 自带的性能分析工具,其中的 “Leaks” 工具可以检测内存泄漏。循环引用是导致内存泄漏的常见原因之一。当一个对象及其相关对象本该释放却没有释放时,Leaks 工具可能会检测到这些泄漏的对象,通过分析对象之间的引用关系,可能发现循环引用。
  2. 解决循环引用(以两个视图控制器相互持有对方为例)
    • 示例代码: 假设我们有 ViewControllerAViewControllerB,初始情况下它们相互持有:
#import <UIKit/UIKit.h>

@interface ViewControllerB;

@interface ViewControllerA : UIViewController
@property (nonatomic, strong) ViewControllerB *viewControllerB;
@end

@interface ViewControllerB : UIViewController
@property (nonatomic, strong) ViewControllerA *viewControllerA;
@end

@implementation ViewControllerA

@end

@implementation ViewControllerB

@end

这种情况下会形成循环引用。

  • 打破循环引用的方法: 将其中一个属性的 strong 改为 weak,例如:
#import <UIKit/UIKit.h>

@interface ViewControllerB;

@interface ViewControllerA : UIViewController
@property (nonatomic, weak) ViewControllerB *viewControllerB;
@end

@interface ViewControllerB : UIViewController
@property (nonatomic, strong) ViewControllerA *viewControllerA;
@end

@implementation ViewControllerA

@end

@implementation ViewControllerB

@end

这样,当 ViewControllerA 被释放时,ViewControllerBViewControllerAstrong 引用计数减一,如果此时没有其他 strong 引用指向 ViewControllerAViewControllerA 会被释放。而 ViewControllerAViewControllerBweak 引用,不会增加 ViewControllerB 的引用计数,当 ViewControllerB 没有其他 strong 引用时,也会被释放,从而打破了循环引用。 3. weak 和 strong 关键字在解决循环引用时的作用

  • strong
    • 作用strong 关键字表示强引用,持有对象,会增加对象的引用计数。在上述例子中,最初两个视图控制器相互用 strong 引用对方,导致引用计数都不会降为 0,从而形成循环引用。
  • weak
    • 作用weak 关键字表示弱引用,不会增加对象的引用计数。当对象的 strong 引用计数变为 0 并被释放时,指向该对象的所有 weak 引用会自动被设置为 nil,避免了野指针的产生。在解决循环引用时,将其中一个引用改为 weak,可以打破循环,使对象在没有其他 strong 引用时能够正常释放。