Xcode/Swift - 无法解决仪器的内存问题

Posted

技术标签:

【中文标题】Xcode/Swift - 无法解决仪器的内存问题【英文标题】:Xcode/Swift - Cannot resolve memory issues with Instruments 【发布时间】:2019-05-10 03:35:46 【问题描述】:

我的应用程序存在内存问题,在达到某个阈值后,应用程序将崩溃。

我被指示使用 Instruments 并选择 Allocation 选项。

但是,对于我的问题,我似乎永远无法得到“直接”的答案,我在下面附上了屏幕截图以帮助更好地描述问题。

内存问题与我创建的任何ViewControllers 或文件无关。而是使用了我不知道的其他库/框架。我已经与这个问题作斗争了几个星期,我已经改变了我的代码/实现了我认为可能已经解决了这个问题的各种方法。但是,没有运气。

有人可以告诉我如何解决这个问题吗?因为我似乎无法强制释放内存,这反过来意味着我的应用程序中有这个巨大的内存错误。

谢谢。

编辑 - 添加了以全分辨率查看图像并返回主屏幕时内存使用情况的屏幕截图。

【问题讨论】:

***.com/questions/30992338/… 另外,请参考medium.com/zendesk-engineering/… 【参考方案1】:

一些想法:

    请参阅 this answer,其中谈到了使用 WWDC 2016 视频 Visual Debugging with Xcode 中的“调试内存图”工具。该工具通常比 Instruments 更容易找到问题。它按目标/框架组织引用计数类型,从而更容易筛选结果。

    但是,如果您要处理的是非引用计数的malloced 数据,那么 Instruments 是您的最佳选择,因为它具有所有的复杂性。但“调试内存图”通常是更好的第一道防线。

    你说:

    内存问题与我创建的任何 ViewController 或文件无关。

    绝对确保您的课程没有埋在列表的下方。数量会少得多,尺寸也更小,所以它们不会出现在顶部,即使它们很可能是问题的根源,它们也会被埋在列表中。坦率地说,如果您的应用程序正在运行,那么您的某些类必须在某处。哈哈。

    同样,“调试内存图”方法比 Instruments 更容易识别您自己的对象。

    如果可能,我建议运行该应用程序,返回到某个您希望内容已发布的主屏幕,然后重复该过程几次。你第一次回到静止状态不是很有启发性,因为会有很多内部缓存在进行。但是在随后您使用该应用程序并返回该主屏幕时,您将有一个更好的示例来说明分配和未释放的内容,而不会出现操作系统在第一次迭代中所做的所有这些噪音:

    (取自 WWDC 2013 Fixing Memory Issues。)

    希望“预热”内存不会太引人注目,但红色区域是我们经常关注的,因为这是我们继续使用应用程序时“浪费”的内容(导致最终崩溃)。

    不幸的是,您的分配曲线根本没有下降,这令人担忧。现在,也许您没有可以返回的“主屏幕”,所以也许这无关紧要。但即使在这种情况下,您的应用程序中也应该有一些状态,您可以看到内存正在恢复。根据提供的信息很难说。

    您没有提到它,但请确认您有哪些调试选项。例如,如果您打开了僵尸,您可能不会看到内存回落到应有的程度。通常,当我们第一次遇到这类问题时,我们会开始启用所有这些调试选项,但它们会对应用程序的内存配置文件产生影响。因此,如果您一直在开启僵尸之类的东西或您拥有的东西,您可能需要确保将它们关闭,以确保它们不是您所看到的行为的一部分。

    我建议模拟内存警告,看看是否可以看到内存正在恢复。确保您的代码正在观察并响应内存警告,尽可能清除内存。

    这都是一般性建议,如果不了解您的代码在做什么,我们无法提供具体建议。我建议你为你的项目创建一个副本,删除不相关的东西,然后继续这样做,直到你有尽可能小的可重现的内存增长示例。通常,该过程足以让您自行诊断问题。但我们不能倾注大量代码。我们需要该问题的minimal, complete, and verifiable example。

底线,“调试内存图”通常是我们的第一级分析。运行应用程序,确定您希望发布但没有发布的对象,然后从那里开始。还要留意有多少这些对象存在(例如,如果您多次看到同一个视图控制器,这表明存在强引用循环或视图控制器的某些循环调用)。

【讨论】:

感谢您的详细回复。我真诚地感谢它。我确实有一个主屏幕,其中使用 SDWebImage 从 Firebase 检索图像/文本数据。内存的主要增加是当我点击图像时,会执行 segue,以更大的分辨率(设备屏幕尺寸)显示特定图像。我确实有一个带有_ = navigationController?.popViewController(animated: true) 功能的后退按钮,并且内存永远不会被释放,而是仍然被存储,每次我点击来自Home 的图像或另一个视图时,内存都会很快建立起来。 我已经经历了显示的每个级别的问题,但是,上面的屏幕截图就是我得到的。我从来没有直接获得对ViewController 的引用,负责内存分配的库范围从CFNetworkQuartzCore,我不知道在我的应用程序中使用了这些库。我不使用Class 我使用Structs 作为为实体创建模型的一种方式。我已阅读 ARC,您认为这是根本原因吗?因为我没有initdeinit 方法。 我还将添加我正在从 Firebase 检索媒体并在 UICollectionView 中显示它们的事实。但是,就下载和调整内容大小而言,所有逻辑都在一个单独的文件中执行 - UICollectionViewCell。这是主要的内存分配问题所在,因为它不会释放内存。 那么当你运行app然后返回home场景时,“debug memory graph”是什么样子的呢?也许您可以编辑您的问题并与我们分享该屏幕快照。 增长幅度很小。内存很少被释放,但是,当内存被释放时,它最多约为 1.5-2mb。【参考方案2】:

Instrument 只是向您展示您的应用如何处理内存/CPU 等的概览。当您在 instrument 中找到某些内容时,您必须对代码进行更改。

请参考:For that you should understand how stong and weak works in ios.

一旦您了解了 iOS 中的 ARC。您将了解代码中的内存泄漏。

诀窍是:

    尝试检查未从仪器内存中删除的对象数量。 然后检查代码是否有对象的强引用,并尝试删除不必要的strong 引用。

希望这会对您有所帮助。

【讨论】:

我不使用Class 我使用Structs 作为为实体创建模型的一种方式。我以前读过这个,你认为这是根本原因吗?因为我没有initdeinit 方法。 如果您有图像加载问题,请参考***.com/a/17569993/9668723 在进行分析时,请检查哪种类型的对象占用了内存并且不会被删除。检查内存中持续存在的对象数量。它可能是任何 uiview、uiimage、您的自定义视图、数组等。检查对象的创建位置。您必须处理这些对象。 我正在使用 SDWebImage 从 URL 检索和加载图像。【参考方案3】:

我解决了我遇到的问题。以防万一将来有人遇到同样的问题,这就是我所做的:

    如果将我的网点/代表声明为weak 每当我在 XCode 要求我使用 self 的块中使用关键字 self 时,我添加了 [weak self] in[unowned self] in 删除单词self 中不需要的所有实例 添加了deinit 并包含了打印声明 添加了调用deinit 方法的断点 在我的viewDidLoad 方法中注释掉了函数,并逐一检查以查看是哪一个/是否导致了问题。

【讨论】:

以上是关于Xcode/Swift - 无法解决仪器的内存问题的主要内容,如果未能解决你的问题,请参考以下文章

简写的闭包数组:Xcode Swift:表达式太复杂,无法在合理的时间内解决

使用仪器解决内存不足警告

目标 C 项目中的 Xcode 8.3 Swift 版本错误 (SWIFT_VERSION)

无法理解仪器数据

使用仪器收到内存警告

内存泄漏仪器警告