0

deinit在所有 VC 中都有方法来检查它们是否被取消初始化

 deinit {
        print("\(self.description) successfully deinitialized")
    }

当我注销时,我看到我所有的视图控制器都被取消初始化并且我LoginViewController的成为根视图控制器。但我仍然可以看到 RAM 使用量为90MB。每次我登录和注销时,它都会不断增加。如果我的视图控制器已取消初始化,是否有可能仍然存在内存泄漏?

我所知道的是,如果视图控制器被取消初始化,则没有内存泄漏。如果存在内存泄漏,视图控制器将不会取消初始化。

我错了吗?请帮忙。

更新:根据卢卡的建议,在这个答案的帮助下,我发现了内存泄漏。但我无法理解这些。有什么办法让它更具可读性吗?

在此处输入图像描述

4

2 回答 2

2

存在三种类型的不良内存问题:

  1. 被遗弃的内存:这是您确实有一些挥之不去的强引用但您不再有权访问这些引用的内存。典型的例子是强引用循环。

    这是 Swift 项目中非常常见的问题。您可以使用“Debug Memory Graph”功能找到这些。请参阅带有 ARC 的 iOS 应用程序,查找对象的所有者当 Leaks 工具未显示内存泄漏时如何调试内存泄漏?.

    顺便说一句,您显然已经确认您的视图控制器正在发布。如果是这样,那就太好了。但它们并不是唯一可以纠缠在强引用循环中的对象。任何引用类型都可能陷入引用循环中。使用“Debug Memory Graph”功能并在左侧面板中查看您的对象,并确保那里没有不应该出现的内容。(顺便说一句,这种技术使您不必到处撒播deinit方法。)

  2. 缓存内存:这是已分配的内存,系统将保留它以防您再次需要它,为您提供高性能访问。除非消耗的内存量很大,否则这通常不会太令人担忧,因为当设备处于内存压力时,通常会自动为您回收这些内存。

    如果您使用UIImage(named:)它可以将图像缓存在内存中。如果使用URLSession,则URLCache可以缓存响应。

    如果在模拟器上进行测试,您可能需要选择“调试”»“模拟内存警告”并查看检索了多少内存(如果有)。

  3. 内存泄漏:这是已分配的内存,但您没有进一步的引用。通常这是由于手动分配从未释放的内存造成的。

    Leaks 工具将帮助您找到这些,但在 Swift 代码中拥有此类材料的情况相对不常见。(或者如果你确实有它们,它们往往是在框架内生成的小东西,而不是在你的控制范围内。)当然,如果你正在做手动核心基础(或核心图形)调用,你可以表现出这些类型的问题,但这不是很常见。

    FWIW,泄漏工具似乎没有报告任何材料内存消耗。所以专注于分配工具(或者,如果可以的话,更好的是“调试内存图”)。您的泄漏似乎不足以解释您在这里谈论的那种内存丢失。

另外,我建议您确认您没有打开内存诊断。例如,僵尸之类的东西会导致内存增长(尽管我没想到你会接近 90mb)。诸如 malloc 堆栈跟踪等工具会增加内存消耗。使用这些工具诊断问题时这很好,但完成后应该关闭。

但是,最重要的是,在深入泄漏之前,我会专注于确认问题不是被遗弃或缓存的内存(因为后者通常很小并且与代码中的任何内容无关)。这些是更常见的问题来源。

于 2020-05-21T17:56:08.340 回答
2

即使 ViewController 被取消初始化,也不一定意味着它将被取消分配。有可能存在一个强大的参考周期。或者可能在您的代码中,为了避免保留循环,您在unowned某处使用引用,而引用计数不会变为零。在强引用计数和无主引用计数都变为零之前,不会释放对象。在这种情况下,尝试使用weak而不是无主,看看它是否有效。弱引用指向称为侧表的东西,而不是直接指向对象,因此不要阻止对象在取消初始化后被释放

查看这篇文章以了解无主引用有时如何阻止对象被释放,以及一般的 ARC。

于 2020-05-28T14:08:54.413 回答