在Xcode 9中使用内存图调试器

我从未真正花费时间来正确学习如何使用乐器。 当然,我知道如何使用Time Profiler和查找泄漏,但是我感觉那里还有很多未开发的潜力。

当Xcode 9与Memory Graph Debugger一起启动时,我真的很兴奋。 也许我可以继续保持懒惰,不学习乐器。 到目前为止,它一直有效。 我可以使用Xcode中的内存规来确定何时可能发生泄漏,然后使用Memory Graph Debugger进行识别。

我最近在App Store上发布了一个名为Subs的应用程序。 它是用于轻松管理所有订阅的。 在开发可以使用Touch ID和Face ID启用的下一个版本时,我通过反复关闭和​​解锁应用程序来测试锁定屏幕。 我注意到每次解锁时内存使用量都在不断增长。

轻击视图调试器旁边的小图图标将加载“内存图调试器”。

滚动浏览左侧的堆内存时,我注意到某些不应该存在的内容。

PageViewController的实例应该只有一个,但其中有五个。 另外,应该只有一个ViewController,在这种情况下,只有五个SubscriptionViewController。 为什么要创建这些其他实例? 更确切地说,为什么不清除先前的那些?

单击其中一个PageViewControllers,将显示其内存图。 它基本上显示了引用此特定PageViewController的所有对象。 您可以看到一些预期的引用,但是有一个引人注目:为什么SubscriptionsViewController引用PageViewController,因为它应该反过来。 原来是罪魁祸首。 除了使用PageViewController引用所有SubscriptionViewControllers之外,还有一个反向引用将PageViewController保留在内存中,然后将所有SubscriptionViewControllers保留在内存中。 单击连接两者的箭头,可以看到参考类型,在这种情况下,参考类型很强。

由于它是一个强大的参考,因此仅将其保存在内存中就足够了。 那么为什么会有一个强有力的参考呢? 因为我把它放在那里(菜鸟把菜鸟当成菜鸟)

在某些情况下,应用程序需要通过SubscriptionViewController中发生的操作来切换页面。 而不是使用通知或委托(我可能应该这样做),我只是向包含页面视图控制器的SubscriptionViewController添加了一个属性。

幸运的是,解决方案非常简单:只需将引用设为弱:

但是如果没有在Xcode 9中使用方便的Memory Graph Debugger来找到它,我不确定如何找到它。 我敢肯定,Instruments可以告诉我这一点,但我不知道在哪里看。