6

对于使用 ARC 的 iOS 应用程序,我们通常会在viewDidUnload?

  1. 将所有实例变量设置为nil

  2. 将所有属性设置为nil

  3. 使用 释放任何上下文CGContextRelease,使用 CGImageCGImageRelease和使用颜色空间CGColorSpaceRelease(释放任何非对象)

  4. 元素不需要特别注意:只需NSMutableArrayNSSetNSMutableArray 和 NSSet 的引用设置为 nil,每个元素都会自动释放。

这样做会处理 ARC 下的大部分内存释放吗?还有其他需要发布的项目吗?

4

2 回答 2

14

很多人误解了viewDidUnload. 特别是,它不是. viewDidLoad在大多数情况下,您的视图控制器将在不viewDidUnload被调用的情况下被释放。出于这个原因,您永远不应该考虑在viewDidUnload适当的平衡中为viewDidLoad.

viewDidUnload已被 Apple 弃用。反对使用它的最佳论据可能是它的标题(我已经包装了):

- (void)viewDidUnload NS_DEPRECATED_IOS(3_0,6_0); // Called after the view
    // controller's view is released and set to nil. For example, a memory warning
    // which causes the view to be purged. Not invoked as a result of -dealloc.`

那是什么viewDidUnload?它背后的想法是视图正在从视图控制器后面卸载。这使您有机会分离任何指向它的指针并清除您可以轻松重建的任何信息。您的视图可能会被重新加载,此时您需要重建所有缓存。苹果是这样描述的:

当内存不足的情况发生并且不需要当前视图控制器的视图时,系统可能会选择从内存中删除这些视图。此方法在视图控制器的视图被释放后调用,这是您执行任何最终清理的机会。如果您的视图控制器存储了对视图或其子视图的单独引用,您应该使用此方法来释放这些引用。您还可以使用此方法删除对您为支持视图而创建但在视图消失后不再需要的任何对象的引用。您不应使用此方法发布用户数据或任何其他无法轻松重新创建的信息。

请记住,viewDidUnload现在应该不需要将对对象的引用清零。如果您按照 Apple 的建议使用 ARC,则您的视图渠道正在将弱引用归零。没有你写,他们会自动被取消viewDidUnload

此外,清除缓存信息更适合didReceiveMemoryWarning,因此您应该改为编写它:

您可以覆盖此方法以释放视图控制器使用的任何额外内存。如果这样做,则此方法的实现必须在某个时候调用超级实现以允许视图控制器释放其视图。如果您的视图控制器持有对视图层次结构中视图的引用,您应该在viewDidUnload方法中释放这些引用。

一般来说,人们放入的东西viewDidUnload最好用viewDidDisappearor处理dealloc。剩下的唯一事情就是在视图控制器仍然打开的情况下,在视图重新加载后的某个时间点需要时,viewDidUnload清空任何可以在不丢失数据的情况下重建的缓存。(同样,这应该在 中处理didReceiveMemoryWarning。)这些缓存应该是惰性构建的;当您的应用再次需要它们时,它会悄悄地重建它们。

那么你应该做什么viewDidUnload呢?如果您使用的是 ARC:没有。甚至不要写它。事实上,自从写了这个答案以来,Apple 已经弃用了viewDidUnload.

对于CGContextReleaseCGContext资源不是 Objective-C 对象。(你指出了这一点,但我想为后代重复。)因此,它不能被 ARC 自动释放。您有责任确保它像旧的手动保留释放 (MRR) 内存管理方案一样被释放和取消。

如果您将此代码放入 中viewDidUnload,则不能保证它会被调用。它必须进去dealloc。你也可以把它放进去viewDidUnload,但是……</p>

所以:

  1. 没有必要也没有帮助。与视图层次结构相比,您的实例变量微不足道。
  2. 没有必要也没有帮助。与视图层次结构相比,您的属性微不足道(只要您的属性不是对视图层次结构的强引用)。
  3. 这将导致内存泄漏,dealloc通常在没有viewDidUnload.
  4. 没有必要也没有帮助。见第 1 点和第 2 点。
于 2012-06-28T06:03:56.593 回答
1

viewDidUnload 有一个棘手的名字,如果你仔细考虑的话,很容易知道里面有什么。

首先你要知道的是 iOS 设备有一个低内存处理方法。这意味着当设备需要更多内存时,它会检查它的哪些应用程序可以释放内存。它通过调用 ViewDidUnload 方法(名称可能不正确)来完成此操作。

所以我们鼓励你在这里将所有可以重建的东西都设置为 nil。(您在 viewdidload 中创建的所有内容)。

例外情况是当您因为获取数据或其他东西可能需要时间而真的无法承受丢失对象时。

如果你不实现这个 viewdidload,你的应用程序将保留它的项目和对象,iOS 将无法从中释放任何东西。

所以基本上就像我说的那样,释放(通过将指向这些对象的元素设置为零)您可以在 viewdidload 中安全地重建的所有内容。(在视图被卸载并想要再次加载后肯定会调用它)

于 2012-06-08T00:23:18.643 回答