实际内存不断增加 - 从视图中删除子视图 - iOS (ARC)

Posted

技术标签:

【中文标题】实际内存不断增加 - 从视图中删除子视图 - iOS (ARC)【英文标题】:Real Memory Constantly Increasing - Removing Subviews from View - iOS (ARC) 【发布时间】:2013-04-27 14:54:38 【问题描述】:

我有一个 iPad 应用程序由于内存不足而在 iPad(第一个型号)上崩溃。

在应用程序中,我有一个主视图,它添加了大约 20 个UIScrollViews(自定义类)作为子视图,每个都包含一个UIImageViewUIImage。当用户移动到下一页时,我从父视图中删除所有这些子视图,然后将 20 个新的UIScrollViews 添加到同一视图中。

如果我分析应用程序的分配和内存泄漏,一切正常 - 当用户左右滚动时,分配的内存保持在 2MB 左右。

但是,如果我在 Activity Monitor 中查看实际内存使用情况,我可以看到每次用户移动到新页面时,实际内存都会增加大约 20MB。最终,在几个新页面之后,应用程序大小达到 150+ MB 并崩溃。

谁能建议可能导致这种行为的原因以及我如何进一步解决此问题?

关于应用结构的更多信息:

在确实加载的视图中,图像使用initWithContentsOfFile 加载到NSMutableArray

【问题讨论】:

【参考方案1】:

您不应该在数组中维护这些图像。图像消耗了不成比例的有限 RAM。有几种方法:

    如果您想保持简单,请不要将图像存储在任何地方。通过initWithContentsOfFile 加载图像,加载UIImageViewimage 属性并收工。

    如果您出于性能原因需要一些 RAM 缓存,您可以使用 imageNamed 而不是 initWithContentsOfFile。当应用收到内存警告时,会自动清除缓存。

    我倾向于使用initWithContentsOfFile,然后手动缓存在我自己的NSCache 中(类似于NSDictionary,除了你可以设置一个countLimit 应该有多少图像等等)。

顺便说一句,您没有描述“用户移动到下一页”时技术上会发生什么。如果您只是刷新现有视图控制器上的现有控件,那么一切可能都很好(一旦您解决了我上面讨论的NSMutableArray 问题)。如果您正在向另一个视图控制器推送/呈现或将控件滚动到屏幕外,但忽略从其超级视图中删除旧的,那么这也会导致问题。你可能想澄清你在那里做什么。

归根结底,您只需要确保当您从一个页面转到另一个页面时,您不会维护对任何旧图像或控件的强引用。

【讨论】:

这一切都发生在同一个 UIView 中。对象被添加到视图中,被删除,然后新的(在本例中为自定义 UIScrollView)对象被添加。我仍然不清楚我最初的问题 - 为什么实际内存仅在将新对象添加到视图时才增加(通过 self.view addSubview x)?对象在 viewDidLoad 方法中放置在数组中,此时实际内存不会增加(它很低且恒定)。 @Ohnomycoco 在这种情况下,我们可能需要查看一些源代码来诊断问题。但很明显,当您转到下一页时,您正在添加一些内容。根据您迄今为止分享的内容无法做出诊断。 @Ohnomycoco 您还可以使用分配工具(如图所示here)来识别分配中的跳跃,突出显示图表的一部分,它会准确地显示导致内存消耗的原因. 谢谢。看起来图像在被放置在屏幕上之前并没有真正加载。从应用程序的角度来看,当图像出现在屏幕上时,内存并没有增加,但从 iPad 实际内存的角度来看,当图像实际放置在屏幕上时,显然会消耗更多的内存。

以上是关于实际内存不断增加 - 从视图中删除子视图 - iOS (ARC)的主要内容,如果未能解决你的问题,请参考以下文章

从父级删除后保留的子视图控制器

iOS 中的内存崩溃,实际内存使用量仅为 5megs

添加删除的子视图 Swift 3 iOS

IOS App的内存使用大小

删除 viewdisappear 上的子视图出现时再次添加 - 不工作 - ios sdk

iOS 从超级视图中删除对象会破坏自动布局并禁用滚动视图