如何在Swift中识别出强大的参考周期?

问题描述 投票:22回答:5

是否有工具或方法在我的SWIFT代码中找到强引用循环?

一个强大的引用循环是当两个类的实例相互引用而没有正确的安全性(weak / unowned)时,因此一旦我创建的所有变量停止引用这些对象,就会阻止垃圾收集器处理它们。

swift reference garbage-collection swift2 strong-references
5个回答
27
投票

您可以将deinit函数添加到将在取消分配对象时调用的类。

如果没有调用deinit,则在您的应用程序运行时,您可以按下Debug Memory Graph按钮(在下面圈出)并检查哪些内容有参考。

Debug Memory Graph Button

使用中间窗格顶部的下拉菜单在类和类实例之间切换。

如果在没有被释放的情况下一次又一次地分配某些内容,您应该看到多个实例,并且您应该能够通过方向图看到其中一个子项是否持有对其父项的强引用。


25
投票

查找强引用循环的方法在Swift中与在Objective-C中相同。

您可以从Xcode运行应用程序,充分运用应用程序来显示循环,然后点击“调试内存图”按钮(debug memory graph)。然后,您可以在左侧面板中选择未发布的对象,它将显示内存图,通常可以显示强大的参考周期:

debug memory graph

有时候内存周期并不那么明显,但你至少可以看到哪个对象保持对相关对象的强引用。如有必要,您可以向后追踪,并确定哪些内容对此有强烈的参考,等等。

有时知道什么类型的对象保留强引用是不够的,并且您真的想知道代码中的哪个位置建立了强引用。如https://stackoverflow.com/a/30993476/1271826所示,“malloc stack”选项可用于识别建立此强引用时调用堆栈的内容(通常可让您识别建立这些强引用的精确代码行)。有关更多信息,请参阅WWDC 2016视频Visual Debugging with Xcode

您还可以使用Instruments来识别泄漏的对象。只需通过使用Allocations工具的应用程序运行应用程序,重复(不只是一次或两次)将应用程序恢复到稳定状态状态,如果内存继续增加,那么您可能会有一个强大的参考周期。您可以使用“分配”工具来识别未发布的对象类型,使用“记录引用计数”功能来准确识别这些强引用的建立位置等。

有关识别和解决内存问题的介绍,请参阅WWDC 2013视频Fixing Memory Issues和WWDC 2012视频iOS App Performance: Memory。那里提出的基本技术今天仍然适用(虽然仪器工具的UI已经改变了一点......如果你想要稍微改变的UI的介绍,请参阅WWDC 2014视频Improving Your App with Instruments)。

另外,“垃圾收集”是指一种非常不同的存储系统,在此不适用。


1
投票

使用仪器检查泄漏和记忆丧失。在仪器上的分配工具中使用标记生成(快照)。

有关如何使用快照查找内存蠕变的信息,请参阅:qazxsw poi

基本上,该方法是运行Instruments分配工具,获取快照,运行代码的迭代并重复另外3到4次快照。这将指示在迭代期间分配但未释放的内存。

要弄清楚结果披露以查看个别分配。

如果您需要查看对象使用仪器的保留,释放和自动释放的位置:

在仪器中运行,在分配中设置“记录参考计数”(对于Xcode 5及更低版本,您必须停止记录以设置选项)。导致应用程序运行,停止录制,向下钻取,您将能够看到所有保留,释放和自动释放发生的位置。


0
投票

你可以bbum blog这样做。正如use Instruments的最后一段所述:

仪器打开后,您应该启动应用程序并进行一些交互,特别是在您要测试的区域或视图控制器中。任何检测到的泄漏都会在“泄漏”部分显示为红线。辅助视图包括一个区域,仪器将向您显示泄漏中涉及的堆栈跟踪,让您深入了解问题所在,甚至允许您直接导航到有问题的代码。


0
投票

非常简单的方法是在deinitialiser中打印

this article

确保您在控制台上看到此行已打印。把deinit放在你所有的viewcontrollers中。如果你无法看到特定的viewcontroller,意味着它们是一个引用循环。可能的原因是委托强,闭包捕获自己,定时器没有被发送等等。

© www.soinside.com 2019 - 2024. All rights reserved.