8

即使在我释放大量内存以响应低内存警告之后,我也无法弄清楚为什么 iOS 会由于内存使用而终止我的应用程序(iPad、iOS 4)。例如,这是一个典型的终止场景,我经常记录内存使用情况——查看“app”使用情况,即每行的第一个 KB 值:

...
2011-12-14 13:25:42.343 Oyster[211:707] Memory usage (KB): app 268256, delta 6472, used 366800/373940
2011-12-14 13:25:43.292 Oyster[211:707] Memory usage (KB): app 273900, delta 5644, used 372444/381024
2011-12-14 13:25:44.159 Oyster[211:707] Memory usage (KB): app 282920, delta 9020, used 381464/389116
2011-12-14 13:25:45.184 Oyster[211:707] Memory usage (KB): app 272140, delta -10780, used 370684/379432
2011-12-14 13:25:46.109 Oyster[211:707] Memory usage (KB): app 260412, delta -11728, used 358956/365900
2011-12-14 13:25:48.443 Oyster[211:707] Received memory warning. Level=2
2011-12-14 13:25:48.454 Oyster[211:707] Memory usage (KB): app 9172, delta -251240, used 107716/112548
(gdb)

您可以看到应用程序内存使用量增加,直到它收到内存警告。然后我正确响应内存警告并释放一堆(250MB!)内存。那时我的应用程序被终止,iOS 进入 iPad 主屏幕。

此处的“内存使用情况”日志与我的logMemoryUsage() 函数一起显示,该函数基于此答案中的代码。

作为记录,我使用SDWebImage将 UIImages 缓存在内存中,但如图所示,它通过清空其缓存(此时相当大)来处理内存警告。我意识到我可以调整 SDWebImage 的缓存以不填充所有可用内存并等待内存警告,但这引出了以下问题......

为什么 iOS 会终止我的应用程序,即使我通过愉快地释放大量内存来响应内存警告?

4

5 回答 5

11

这是内存管理等良好实践的一般答案。通常,听起来内存缓存变得太大了,即使它释放对象以响应内存警告,到那时为时已晚。

  1. 内存警告本质上不是“坏的”,你无法避免它们。它们是 iOS 生命周期的正常部分,您必须通过释放所有对象中的所有非必要数据来正确处理它们,以确保您的应用程序以负责任的方式运行。即使您的应用程序占用空间很小,您仍然可能会收到有关设备上其他条件的内存警告(例如正在使用的其他应用程序等)。我在UIApplicationDidReceiveMemoryWarningNotification这里指的是运行时通知。调试器消息(例如“收到内存警告。Level=2”)是特定于您的应用程序的,尽管它们不一定与接收运行时通知相关。

  2. 我不太了解SDWebCache。我会查看实现并确保它有效地释放内存。例如,也许@autoreleasepool在相关地方使用将有助于它在运行循环中更有效地释放对象。

  3. 您应该努力使您的应用程序的内存占用尽可能受到限制。对图像数据使用内存缓存很好,但我会限制它的大小。如果您的应用程序的占用空间大于 250MB,即使您处理内存警告,它也会被终止,我并不感到惊讶。到那时可能为时已晚。

  4. 您可能有其他问题导致/促成终止。正如评论所建议的那样,您需要在仪器中进行更多调试以查找泄漏、错误访问等。在此处发布崩溃日志会有所帮助。

于 2011-12-16T19:51:30.230 回答
1

在处理大图像(每张图像 4Mb)时,您可能会冒内存不足的风险,而不会收到内存不足的警告。

最好的办法是真正防止您的内存使用量增长过多。图像的加载速度使得缓存很好,但并不是真正必要的。一旦不再使用内存,最好通过释放内存来降低使用率。

祝你好运,如果你找到值得分享的东西,请告诉我们。

于 2011-12-23T13:27:44.660 回答
1

如果没有更多信息,我无法知道这些是否适用于您,但在尝试清理内存警告后,我通常会遇到某些问题:

  • 未知的循环引用会阻止内存像您期望的那样被释放。使用仪器来寻找它们。我最近修复了一个我不小心在块中使用 self 导致保留的情况。当出现内存警告时,我们注意到了这一点,并且我们无法通过释放该资源来很好地从警告中恢复。
  • 清理资源——或自动释放资源——已经释放了一些仍然需要的东西。你可能在你不期望的地方有一个 nil,或者你可能对一个僵尸进行操作。检查您的保留和清理,尤其是代表的取消。打开僵尸和异常断点。

通常最好的解决方案是首先防止内存警告发生。

于 2011-12-14T22:29:23.390 回答
1

检查图像转换的代码。SDWebImage 项目中有一些代码用于缩小图像,对所选图像应用一些变换和旋转技术。它实际上并没有使用太多来缩小尺寸,但有时会引起内存警告。评论该代码并尝试构建您的应用程序。

我在我的应用程序中遇到了同样的问题。我曾试图评论转换代码。问题得到解决。你也可以试一试。

于 2011-12-22T15:37:41.157 回答
1

2 级内存警告是紧急的。您的应用在收到 2 级警告之前可能会收到一个或多个 1 级警告,此时您应该采取行动。

根据我的经验,当您的应用收到 2 级警告时,几乎总是为时已晚,而且无论如何它都会被杀死。

于 2011-12-22T23:51:17.357 回答