iOS:didReceiveMemoryWarning的帮助:
我是我的开发过程中追踪崩溃和内存泄漏的一部分。 作为一个策略,你是否把任何NSLog的消息或一些这样的通知didReceiveMemoryWarning:
这个方法的文档相当稀less。 是否准确地说,在发生崩溃之前,UIViewController会触发该方法? 即使是与仪器一起前进,这是一个起点吗?
好的,有几件事要注意:
- didReceiveMemoryWarning将在内存不足崩溃之前调用。 没有其他崩溃。 如果正确处理警告并释放内存,则可以避免出现内存不足的情况,也不会崩溃。
- 您可以在硬件菜单下的模拟器中手动触发内存警告。 强烈build议您这样做来testing您对didReceiveMemoryWarning的处理。
- 仪器可以帮助你debugging泄漏(尽pipe不是全部) – 对于崩溃并不是那么有用。
- 不,我不亲自使用NSLog – 我只是在debugging时断开内存警告。
如果用户留下了一些应用程序,您可以使用的内存很less。 所以有时候,只有在1 MB的使用量之后,系统才会调用didReceiveMemoryWarning
。
系统在所有视图控制器上调用这个方法,如果你在每个视图控制器中放置一个NSLog,你会注意到这一点。
然后自动的方法viewDidUnload
将由系统在您的所有视图控制器(而不是dealloc
)调用。 所以你必须把所有的释放指令放在那里。
你必须进行大量的实验,因为如果你的应用程序是复杂的,那么在pipe理它之前你会遇到很多崩溃。
更新从iOS 6开始, UIViewController
视图不再被卸载以响应内存警告。 相反,只要尽力释放任何资源,您可以合理地重新创build(如caching数据),当didReceiveMemoryWarning
被调用。
UPDATE
当我是一个愤怒的年轻人,我写了我原来的答案; 时代已经改变,基本上,这是错误的。
如果你有一个单一的视图控制器的应用程序,并收到内存警告,你可以做的事情不多。 但是如果你有多个视图控制器的话,事情会发生巨大的变化,因为你可以卸载与非最前面的控制器相关的所有状态。 事实上, [UIViewController didReceiveMemoryWarning]
会通过卸载不可见的视图给你正确的方向(惊喜!)。 当最前面的视图控制器被解散时,底层视图被重新加载,并且至多用户应该只知道延迟,即使在内部你的应用可能已经完成了重新启动。
这不是一些细节,你可以很容易地翻新,你需要从头开始记住内存使用,并devise你的多视图应用程序到干净的无法加载UIViewController
件。 事实上,值得让你的代码与模拟器兼容,只是为了使用它的内存警告function。
当记忆丰富的时候,没有什么东西是卸载的,一切都是如丝般光滑的,而当记忆力低下的时候,事情会继续下去,尽pipe比较缓慢。 现在我想说这个有限内存问题的解决scheme是理想的。
为了充分利用这个内存技巧,重载UIViewController
方法viewDidLoad
, viewDidUnload
和viewWillUnload
(iOS5,如果卸载状态需要你的视图依然存在,例如如果你不想泄露你的OpenGL纹理和渲染缓冲区,您可以通过重载didReceiveMemoryWarning
和跟踪您的视图的可见性来模拟iOS4。
原来的,更有生气的答案
didReceiveMemoryWarning
绝对没用。
没有保证,如果你释放记忆(甚至所有的),你不会被杀死。
在我的痛苦经历中,它通常在2.x / 3.0上是这样工作的:
-
mediaserverd泄漏了一堆内存
-
我的应用程序被杀害
不幸的是,收割者从来没有想过杀死mediaserverd。
所以,如果内存使用不是你的错,你真的只有两个select:
-
要求用户重新启动(用户认为这是你的错,写一个严厉的评论)
-
希望肇事者崩溃(mediaserverd经常要求!)
didReceiveMemoryWarning的目的是为了让您有机会释放内存或popup视图,以避免崩溃。 你不会在任何可预测的地方收到它,因为它取决于用户在做什么。 例如,如果用户正在聆听iPod,则可用内存会减less,您将会收到更快的内存。
一般的经验法则是,你有大约8MB的RAM工作。 当你接近的时候,你可以期待事件被提出。 如果你故意占用那么多RAM,你应该有一个计划去做一些事情。