iOS:didReceiveMemoryWarning 的帮助:

Posted

技术标签:

【中文标题】iOS:didReceiveMemoryWarning 的帮助:【英文标题】:iOS: helpfulness of didReceiveMemoryWarning: 【发布时间】:2010-10-09 14:30:53 【问题描述】:

我正在开发过程中跟踪崩溃和内存泄漏。作为一种策略,您是否将任何 NSLog 消息或某些此类通知放入 didReceiveMemoryWarning:?此方法的文档相当稀少。准确地说,在崩溃发生之前,UIViewController 会触发该方法吗?在使用 Instruments 之前,这是一个起点吗?

【问题讨论】:

【参考方案1】:

好的,有几点需要注意:

didReceiveMemoryWarning 将在内存不足崩溃之前调用。不是其他崩溃。如果您正确处理警告并释放内存,则可以避免内存不足的情况并且不会崩溃。 您可以在硬件菜单下的模拟器中手动触发内存警告。强烈建议这样做以测试您对 didReceiveMemoryWarning 的处理。 Instruments 可帮助您调试泄漏(尽管不是全部)- 它对崩溃并没有那么有用。 不,我个人不使用 NSLog - 我只是在调试时断点内存警告。

【讨论】:

嗨 Airsource,我能问一下“模拟器 -> 硬件 -> 模拟内存警告”是做什么用的吗?每当我单击它时,我只会收到一条消息“收到模拟内存警告”。在控制台中。我如何使用它来“解决问题”?谢谢。 @lionfly - 为了响应内存警告,您应该尽可能多地释放内存。模拟内存警告可让您检查(和调试)该代码路径。【参考方案2】:

如果用户让某些应用程序处于打开状态,那么可供您使用的内存将非常少。 所以有时候didReceiveMemoryWarning只有在使用1MB后才能被系统调用。

系统会在所有视图控制器上调用此方法,如果您在每个视图控制器中放置一个 NSLog,您会注意到这一点。

然后,系统将自动在您的所有视图控制器(不是dealloc)上调用方法viewDidUnload。所以你必须把你所有的释放指令放在那里。

您必须进行大量实验,因为如果您的应用程序很复杂,您将面临很多崩溃,然后才能很好地管理它。

【讨论】:

【参考方案3】:

更新ios 6 开始,UIViewController 视图不再卸载以响应内存警告。相反,在调用didReceiveMemoryWarning 时,尽量释放您可以合理重新创建的任何资源(例如缓存的数据)。

更新 当我还是一个愤怒的年轻人时,我写下了我原来的答案;时代变了,基本上都是错的。

如果您有一个带有单个视图控制器的应用并且收到内存警告,那么您无能为力。但是,如果您有多个视图控制器,情况会发生巨大变化,因为您可以卸载 all 与非最前端控制器关联的状态。事实上,[UIViewController didReceiveMemoryWarning] 将通过为您卸载不可见的视图(惊喜!)来促使您朝着正确的方向前进。当最前面的视图控制器被关闭时,底层视图会重新加载,即使您的应用内部可能已经完全重启,用户最多也应该知道延迟。

这不是您可以轻松改造的一些细节,您需要从一开始就牢记内存使用情况,并将您的多视图应用程序设计成完全可卸载的UIViewController 部分。事实上,让你的代码与模拟器兼容只是为了使用它的内存警告功能是值得的。

当内存充足时,什么都没有卸载,一切都如丝般顺滑,当内存不足时,事情会继续工作,尽管速度会更慢。现在我要说,这种有限内存问题的解决方案是理想的。

要利用这个记忆客厅技巧,重载 UIViewController 方法 viewDidLoad,viewDidUnload, 和 viewWillUnload(iOS5,如果卸载状态需要您的视图仍然存在,例如如果您不想泄漏 OpenGL 纹理和渲染缓冲区,则在 iOS4 上您可以通过重载 didReceiveMemoryWarning 并跟踪视图的可见性来模拟这一点) .

原创,更有胆量的答案

didReceiveMemoryWarning 绝对没用。

无法保证如果您释放内存(甚至全部) 你不会被杀。

在我的痛苦经历中,它通常在 2.x/3.0 上这样工作:

    mediaserverd 泄露大量内存

    我的应用程序被杀死

不幸的是,收割者从未想过要杀死 mediaserverd。

所以如果内存使用不是你的错,你真的只有 两个选择:

    要求用户重启(用户认为是你的错,写了严厉的评论)

    希望罪魁祸首崩溃(mediaserverd 经常有义务!)

【讨论】:

时间在前进。 viewDidUnload 现在被这些注释弃用了,“视图不再在内存不足的情况下被清除,所以这个方法永远不会被调用。”和“在 iOS 6 及更高版本中,不需要清除视图控制器中对视图和其他对象的引用。” - source 前几天我还在考虑更新这个答案!【参考方案4】:

didReceiveMemoryWarning 的目的是让您有机会释放内存或弹出视图以避免崩溃。您不会在任何可预测的时间收到它,因为它取决于用户在做什么。例如,如果用户正在收听 iPod,则可用内存较少,您将更快收到。

一般的经验法则是您可以使用大约 8MB 的 RAM。当您接近它时,您可以预期该事件会被引发。如果你故意占用这么多内存,你应该有一个计划来解决它。

【讨论】:

以上是关于iOS:didReceiveMemoryWarning 的帮助:的主要内容,如果未能解决你的问题,请参考以下文章

IO模型--阻塞IO,非阻塞IO,IO多路复用,异步IO

IO复用阻塞IO非阻塞IO同步IO异步IO

四种IO模型‘阻塞IO/非阻塞IO/信号驱动IO/异步IO‘

5种IO模型阻塞IO和非阻塞IO同步IO和异步IO

网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO

同步IO异步IO阻塞IO非阻塞IO之间的联系与区别