6

我是一个大型团队的一员,负责处理 iOS 遗留代码,目标 iOS 环境为 4.3 及更高版本。我见过其他开发人员签入派生自NSObject但没有dealloc方法的类。我也见过UIViewController不包含viewDidUnload方法的后代。当我询问这段代码时,通常的回答是“别担心,ARC 现在会处理这个问题。”

我知道viewDidUnload当iOS遇到内存不足的情况时调用它,目的是通过释放可以通过调用重新创建的对象来释放内存viewDidLoad,并且dealloc当对象的保留计数达到零时调用。对于 UIViewController 对象和后代,这可能意味着之前可能会或可能不会调用“viewDidUnload” dealloc

所以这是我的问题:在 iOS 6 之前的 iOS 版本上使用 ARC 时是否仍然需要方法deallocviewDidUnload

如果答案是“是! ”那么我将需要充分的理由和/或文件来进行论证。

期待您的回复。(感谢汤米帮助我加强了我的问题。)

4

2 回答 2

14

viewDidUnload 已弃用。因此,无论 ARC 是什么,您不仅不需要而且不应该使用。声明的理由是视图不再因内存不足警告而被清除(大概是因为它们现在对总数的贡献太小,不值得响应性打击);viewDidLoad如果部分理由是很多人认为他们可以释放内部创建的所有资源viewDidUnload并且仅此一项就可以防止泄漏,我不会感到惊讶。这不是真的,因为viewDidUnload仅当视图因内存不足警告而被卸载时才调用。在正常的生命周期中不会调用它。

根据ARC 的新规则

如果您需要管理资源而不是释放实例变量,您可以实现一个 dealloc 方法。您不必(实际上您不能)释放实例变量

编辑:特别评论4.3+...

ARC 不会viewDidUnload为您实现一个版本。viewDidLoad/循环的要点viewDidUnload是,如果您retain出于任何原因进入视图层次结构的任何部分,那么您将导致它不会在内存不足警告时自动释放,但这样做不会给您带来任何好处,因为只要接下来加载视图,您保留的任何内容都将被新副本替换。因此,如果您无论如何strong IBOutlet都拥有位于下面层次结构中的视图,self.view那么理想情况下,您会在viewDidUnload. 即使您有weak引用,这也是防止自己继承任何悬空指针的好地方。

从 iOS 5 开始,您可以拥有自归零弱引用,因此viewDidUnload如果您支持 5+,则使用这些而不是实现将是可行的方法。对于 4.3,如果您使用强引用并省略viewDidUnload,您最终可能会像 Apple 所希望的那样彻底阻止对低内存警告的响应,但您不会泄漏内存。如果您使用弱引用,那么在您可能没有视图的时候(即,任何时候您没有显示但视图之前已加载 - 设置器)时,您需要小心不要引用任何这些对象在控制器上同时调整视图但受另一个视图影响的控制器是一个经典示例;例如,如果您通过键值观察来更新字段)。

您可以使用模拟器的“模拟内存警告”在一定程度上测试和调试这些东西。

dealloc无论 iOS 版本如何,ARC 提供的都是相同的。但是它只涵盖了 Objective-C 对象。当他们说您不能释放实例变量时,他们的意思是字面意义上的release向他们发送消息。假设您有 Core Foundation 对象或执行了纯 C 内存分配,那么您将希望实现一个dealloc处理所有这些对象的方法。

显然 Instruments 和 Leaks 工具是测试和调试该区域的方法;任何时候内存泄漏都要小心检查创建该内存的对象类型是否也被泄漏。直接对象可以很好,但如果它没有dealloc因为其他人泄漏它,它的分配将出现在泄漏列表中。

于 2012-09-27T22:03:10.403 回答
6

viewDidUnload现在已弃用并且不再被系统调用(从 iOS 6 开始)。它从来没有像苹果希望的那样有用,而且麻烦多于它的价值。这与 ARC 无关。

dealloc在 ARC 下通常不需要,但在需要非 ARC 资源管理的情况下仍然是必需的。例如,如果您需要使用free(),或者以其他方式释放资源。这也是一个将自己作为观察者或代表移除的好地方。但是现在很多类都不需要dealloc.

于 2012-09-27T22:01:35.017 回答