应该将 viewDidUnload 中的哪些工作移至 didReceiveMemoryWarning?

Posted

技术标签:

【中文标题】应该将 viewDidUnload 中的哪些工作移至 didReceiveMemoryWarning?【英文标题】:What works in viewDidUnload should be moved to didReceiveMemoryWarning? 【发布时间】:2012-10-03 12:27:00 【问题描述】:

在新的 ios 6 中,viewDidUnload 已被弃用,我们被指示改用didReceiveMemoryWarning 来管理 UIViewController 实例和子类中的对象。在didReceiveMemoryWarning 中将 nil 分配给 UIView 种类是否同样有效,就像在 viewDidUnload 中所做的那样?

我问这个是因为这两种方法的工作方式似乎不同。似乎 didReceiveMemoryWarning 不能保证再次调用 viewDidLoad 以重新实例化任何必要的 UIView。

我怀疑在 iOS 6 中,无需手动释放 UIView 即可完成内存管理。请帮助我了解我在理解 UIViewController 的生命周期时遗漏了什么。

【问题讨论】:

【参考方案1】:

我现在首选的方法如下:

- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];
    if (self.isViewLoaded && !self.view.window) 
        self.view = nil;
    
    // Do additional cleanup if necessary

请注意,测试 self.isViewLoaded 是必不可少的,否则访问视图会导致它加载 - 甚至 WWDC 视频也往往会错过。

如果您对子视图的其他引用是弱引用,则不必在此处将它们设为 nil,否则您也想将它们设置为 nil。

您应该完全摆脱viewDidUnload,并且那里的每个代码都应该移动到适当的位置。无论如何,它不能保证在 iOS 6 之前被调用。

【讨论】:

另外,如果这是一件重要的事情,你不认为基础实现会这样做吗? 你说得对,这不是必需的。对于基于图像的视图的草率实现,内存量可以从几个字节到几十兆字节变化很大。所以我们可以很容易地释放它,但我们不必这样做。尤其是对于很多控制器,它仍然可能是一个好主意,而且占用空间越小,应用程序就越有可能不会在后台被杀死。因此,我的建议是更多地取消它除非您确定保留它很便宜。当然,设置成本也需要考虑。【参考方案2】:

viewDidUnload: 的 iOS 参考中,它指出这在 iOS 6 中已被弃用,因为

视图不再在内存不足的情况下被清除,所以这 方法永远不会被调用

它没有说明将此代码放在didReceiveMemoryWarning: 中。由于在内存不足的情况下不再清除视图,因此您不必担心在任何一种方法中都会清理视图。

【讨论】:

这是正确答案。从 ios6 开始,消除视图不是您关心的问题。 viewDidLoad 未被弃用,viewDidUnload 被弃用。至于不退出,我建议观看 WWDC 2012 视频,演讲者经常推荐这个。同样,这不是必须的,但他们清楚地声明要在此处释放尽可能多的内存(包括视图)。文档说不再调用该方法,因为人们滥用此方法进行其他清理并经常依赖它。所以不,这个答案是不正确的。这是相当错误的。苹果刚刚给了程序员更多的控制权。 “在内存不足的情况下不再清除视图”意味着您肯定必须担心清理didReceiveMemoryWarning: 中的视图?否则不会释放视图,也不会减少内存使用量。 当然,我可能误解了文档的含义。 Joe Conway's blog on this topic 解释了如何 iOS 6 重新获得didReceiveMemoryWarning 的内存,以及为什么视图本身不再被清除。 @adamjansch 如果我的赏金引起了人们对这个问题的关注,那么提供赏金是正确的决定。我的想法和你的完全一样,我仍然很难相信没有必要再打电话给viewDidUnload。感谢您的博文。【参考方案3】:

Eiko 的回答不正确,当收到内存不足警告时,我们不应该将self.view 设置为nil。这样做是没有用的,而且可能有害。

iOS 6 会自动释放当前未显示的视图位图,详情请参阅http://thejoeconwayblog.wordpress.com/2012/10/04/view-controller-lifecycle-in-ios-6/。

【讨论】:

以上是关于应该将 viewDidUnload 中的哪些工作移至 didReceiveMemoryWarning?的主要内容,如果未能解决你的问题,请参考以下文章

Iphone 开发 - ViewDidUnload

将世界中的物体移向静止的相机

没有为 UIscrollView 中的 viewControllers 调用 ViewDidUnload

NSNotification、addObserver 和 removeObserver - ViewDidUnload 和 dealloc 中的 removeObserver?

didReceiveMemoryWarning、viewDidUnload 和 dealloc

在内存警告后调用 viewdidunload 后视图从不重新加载(viewdidload 从不调用)