内存管理挑战
- 循环引用问题:委托对象和被委托对象之间若相互持有强引用,会形成循环引用,导致内存无法释放。例如,ViewController作为委托对象持有被委托对象(如一个自定义的DataLoader)的强引用,而DataLoader又将ViewController设为委托并强引用它,这就形成了循环。
- 过早释放问题:如果委托对象过早释放,被委托对象在调用委托方法时可能会访问到已释放的内存,导致程序崩溃。比如,视图控制器销毁时没有正确处理委托关系,被委托对象仍然尝试调用委托方法。
可能导致的问题
- 内存泄漏:循环引用会使得相关对象的引用计数永远不会降为0,从而导致内存无法被释放,造成内存泄漏,随着程序运行,内存占用不断增加。
- 程序崩溃:当访问已释放的委托对象时,会引发野指针错误,导致程序崩溃,影响用户体验。
避免问题的方法
- 使用弱引用:在被委托对象中,将委托属性声明为弱引用(
weak
),这样就不会增加委托对象的引用计数,从而打破循环引用。例如:
@property (nonatomic, weak) id<MyDelegateProtocol> delegate;
- 正确的生命周期管理:在委托对象销毁前,确保解除与被委托对象的委托关系。比如在视图控制器的
dealloc
方法中,将自己从被委托对象的委托列表中移除,防止被委托对象继续持有无效的委托引用。
- (void)dealloc {
// 假设dataLoader是被委托对象
self.dataLoader.delegate = nil;
}
- 使用
unsafe_unretained
(较少用):与weak
类似,但unsafe_unretained
不会在对象释放后自动将指针置为nil
,可能导致野指针,使用时需谨慎。例如:
@property (nonatomic, unsafe_unretained) id<MyDelegateProtocol> delegate;