MST

星途 面试题库

面试题:Objective-C协议与委托在运行时的内存管理

在使用Objective-C协议与委托时,运行时的内存管理会面临哪些挑战?比如委托对象和被委托对象之间的内存引用关系可能会导致什么问题,如何避免这些问题?
38.5万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

内存管理挑战

  1. 循环引用问题:委托对象和被委托对象之间若相互持有强引用,会形成循环引用,导致内存无法释放。例如,ViewController作为委托对象持有被委托对象(如一个自定义的DataLoader)的强引用,而DataLoader又将ViewController设为委托并强引用它,这就形成了循环。
  2. 过早释放问题:如果委托对象过早释放,被委托对象在调用委托方法时可能会访问到已释放的内存,导致程序崩溃。比如,视图控制器销毁时没有正确处理委托关系,被委托对象仍然尝试调用委托方法。

可能导致的问题

  1. 内存泄漏:循环引用会使得相关对象的引用计数永远不会降为0,从而导致内存无法被释放,造成内存泄漏,随着程序运行,内存占用不断增加。
  2. 程序崩溃:当访问已释放的委托对象时,会引发野指针错误,导致程序崩溃,影响用户体验。

避免问题的方法

  1. 使用弱引用:在被委托对象中,将委托属性声明为弱引用(weak),这样就不会增加委托对象的引用计数,从而打破循环引用。例如:
@property (nonatomic, weak) id<MyDelegateProtocol> delegate;
  1. 正确的生命周期管理:在委托对象销毁前,确保解除与被委托对象的委托关系。比如在视图控制器的dealloc方法中,将自己从被委托对象的委托列表中移除,防止被委托对象继续持有无效的委托引用。
- (void)dealloc {
    // 假设dataLoader是被委托对象
    self.dataLoader.delegate = nil; 
}
  1. 使用unsafe_unretained(较少用):与weak类似,但unsafe_unretained不会在对象释放后自动将指针置为nil,可能导致野指针,使用时需谨慎。例如:
@property (nonatomic, unsafe_unretained) id<MyDelegateProtocol> delegate;