依靠确定性dealloc(例如:清理)是合法的做法吗?
由于ARC,甚至是手工引用计数,本质上是确定性的,我想知道其他人在dealloc上立即调用依赖的想法(相对地,考虑自动释放池)。
在其他现代编程语言中,如C#,当您需要确定性清理时,会使用类似于处理的模式。我想,Obj-C垃圾收集也会鼓励这种行为。
所以,有了这个说,一个例子是UIViewController,它取消了dealloc中的未完成的操作,而不是试图编写viewDidDisappear有时令人沮丧的语义。
另一个例子是分别在init和dealloc中隐式打开和关闭的流对象,而不是要求打开或关闭。
由于Apple已弃用GC,我认为这些类型的模式不会很快被破坏,并且它们非常方便,但我找不到任何关于是否应该鼓励它的文档。
答案 0 :(得分:2)
你是绝对正确的,你可以依赖dealloc
在最后一次参考发布后相对不久被调用(手动或通过ARC,无关紧要)。与在系统有空闲时间时调用终结器的GC不同,或者在某些情况下从不调用终结器时,dealloc
被非常可靠地调用。 Apple允许甚至鼓励使用此模式,建议我们在dealloc
内执行所有资源清理任务。
但这并不意味着您应该完全依赖dealloc
。例如,看看NSStream
类:它为您提供了一个明确的close
方法,让您可以随意强制关闭流,而无需等待dealloc
的调用。如果资源非常昂贵(文件句柄,信号量等),这是一个非常好的模式:释放这些资源的主要机制应该是一个单独的close
方法。 dealloc
方法也应该释放资源,但它也应该发出警告,通知您错过了close
的来电。
答案 1 :(得分:1)
无论您的内存管理系统如何,将昂贵的资源(例如文件和套接字,图像,视图,大内存分配等)绑定到对象生存期都是有风险的。即使你是手动保留&释放时,您可能会无意中将某个对象保留在某处并忘记它(否则会不必要地延迟释放)。 ARC使这些事情发生的可能性更大,因为保留来自哪里以及相应的版本何时生效都不太明显。当然GC让它完全无限期。
通常,对于昂贵和/或有限的资源,您应该尝试遵循独资模式。是的,您仍然可以正常保留/释放以防止过早释放,但主导所有者应该明确定义并负责在完成后清除对象 - 例如调用无效,或关闭,或任何适当的。这在很多常见情况下都很有意义 - 例如,您通常知道何时完成文件或套接字,因此即使它们恰好封装在某个包装类中,您也应该明确地将它们关闭。
在某些情况下,这还可以帮助查找原本会隐藏或难以追踪的错误。例如,如果文件包装类在文件关闭后调用read或write时引发异常,则很快就会捕获这些情况。如果您在思考时没有关闭文件,那么读取和写入就会像往常一样发生,您可能不会注意到文件中包含意外数据。
您也可以使用相同的原则来打破保留周期。