3

依赖确定性 dealloc(例如:用于清理)是一种合法的做法吗?

由于 ARC,甚至手动引用计数,本质上是确定性的,我想知道其他人对依赖立即调用 dealloc 的想法(相对而言,考虑 autoreleasepool)。

在其他现代编程语言(如 C#)中,当您需要确定性清理时,会使用类似 dispose 的模式。我会想象带有垃圾收集的 Obj-C 也会鼓励这种行为。

因此,话虽如此,一个例子是 UIViewController,它取消了 dealloc 中的未完成操作,而不是尝试围绕 viewDidDisappear 有时令人沮丧的语义进行编程。

另一个示例是流对象,它分别在 init 和 dealloc 中隐式打开和关闭,而不需要调用 open 或 close。

由于 Apple 已弃用 GC,我想这些模式不会很快被打破,而且它们非常方便,尽管我找不到任何关于是否应该鼓励这样做的文档。

4

2 回答 2

2

您是绝对正确的,您可以依赖在dealloc最后一个引用发布后相对较快的调用(手动或通过 ARC,没关系)。与 GC 不同,在系统有空闲时间时调用终结器,或者在某些情况下从不调用,它dealloc被非常可靠地调用。Apple 通过建议我们应该在内部执行所有资源清理任务来允许甚至鼓励使用这种模式dealloc

但是,这并不意味着您应该dealloc完全依赖。例如,看一下NSStream类:它为您提供了一个显式close方法,让您可以随意强制关闭流,而无需等待调用的dealloc发生。如果资源非常昂贵(文件句柄、信号量等),这是一个非常好的模式:释放这些资源的主要机制应该是一个单独的close方法。该dealloc方法也应该释放资源,但它也应该发出警告,通知您您错过了close.

于 2012-11-30T02:57:35.817 回答
1

无论您的内存管理系统如何,将昂贵的资源(例如文件和套接字、图像、视图、大内存分配等)绑定到对象生命周期都是有风险的。即使您手动保留和释放,您也可能在不知不觉中将对象保留在某处并忘记它(或以其他方式不必要地延迟其释放)。ARC 使这些事情更有可能发生,因为保留的来源以及相应的发布何时生效并不那么明显。当然,GC 使这一切变得完全不确定。

通常,对于昂贵和/或有限的资源,您应该尝试遵循独资模式。是的,您仍然可以正常保留/释放以防止过早解除分配,但是应该明确定义主导所有者并负责在完成时清除对象-例如调用无效或关闭或任何适当的方法。这在很多常见情况下都非常有意义 - 例如,您通常知道何时完成了文件或套接字,因此即使它们恰好封装在某个包装类中,您也应该明确地关闭它们。

在某些情况下,这还可以帮助找到原本隐藏或难以追踪的错误。例如,如果您的文件包装类在文件关闭后调用 read 或 write 时引发异常,您很快就会发现这些情况。然而,如果您在认为已完成文件时没有关闭文件,则读取和写入将照常进行,您可能不会注意到文件中包含意外数据。

您也可以使用相同的原则来打破保留周期。

于 2012-11-30T07:19:36.693 回答