【问题标题】:Navigation Controller back button is not releasing memory of dismissed viewController导航控制器后退按钮未释放已关闭视图控制器的内存
【发布时间】:2018-04-27 14:35:41
【问题描述】:

这里是新手问题。 想象一个带有 2 个 vc(A 和 B)的非常基本的故事板。 A 嵌入在 navController 中。 A 有一个 collectionView 显示图像网格。 B 正在大显示单击的网格项目。如此简单的列表->详细信息。

用 IB 完成所有操作,我从 collectionView 单元格项目 ctrl 拖动到 B 并选择“显示(例如推送)”segue。

现在,当我运行应用程序并多次单击网格中的图像,然后单击“

这会导致大量内存被使用并且每次都在增长。

我发现了一些关于 unwind 和 pop to root vc 的帖子,但所有帖子都在处理程序化导航。这只是使用 IB 完成的简单故事板的例子。

预期:A->B->A。内存:A

现实:A->B->A。内存:A,B

如何避免为那些被解雇的 vc 保留内存?

在 A 我有:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "dreamDetail" {
        let newViewController = segue.destination as! DreamDetailViewController
        newViewController.dream = allDreams?[(collectionView.indexPathsForSelectedItems?.first?.item)!]
        newViewController.dreams = allDreams
    }
}

在 B 我有:

weak var dream: DreamRealm?{
    didSet {
    }
}

var dreams: [DreamRealm]?{
    didSet {
    }
}

DreamRealm 只是一个 Realm 模型。

class DreamRealm: Object {

@objc dynamic var filename: String? = nil
@objc dynamic var path = ""

【问题讨论】:

  • 您的代码中其他地方的 A->B 和 B->A 之间是否存在强引用?
  • 你是如何从 B 导航到 A 的?
  • @ReinierMelian 正如我在描述中所说,只需按导航控制器上的后退按钮即可。没有自定义代码。
  • @TusharSharma 看起来是的。但我刚刚使用 Instruments/Leaks 工具分析了该应用程序,并在进行导航时显示所有绿色检查。

标签: ios swift memory-leaks uiviewcontroller


【解决方案1】:

作为@Arrabidas92 答案的补充:

  • 注意双重嵌套块

我使用以下代码构建了一个保留循环:

navigationItem.reactive.rightBarButtonItems <~ user.producer.map{ $0
    .map{ [weak self] user in
        guard let self = self else { return [] }

我想,内部地图的[weak self] 就足够了。它不是。外部地图已经捕获了自我(将其传递给内部?)。写完user.producer.map{ [weak self] $0之后,我的保留周期就消失了。

【讨论】:

    【解决方案2】:
    1. 所有与 UI 元素(在视图控制器中)的 IB 连接必须是 weak!
    2. 尝试在dealloc方法中释放strong对象;

    有时在垃圾收集器释放对象之前会有一些延迟,执行“显示”和“返回”,等待大约 10 秒,看看是否释放了更多内存。

    【讨论】:

      【解决方案3】:

      为避免保留被关闭的 VC 的内存,您需要检查是否存在保留循环。

      为了帮助您检查您的 VC 是否正确取消初始化,您可以实现一个名为 deinit 的方法。这是当您的 VC 处于 deinit 状态且不再在内存中时调用的方法。您可以打印一条消息以查看是否是这种情况。

      如果不是这样,您可能在代码中的某处有一个强引用。您需要通过使用weak 关键字或unowned 弱化您的引用来避免它,或者如果您不需要它就删除它。

      【讨论】:

      • 我试图在新项目上复制问题并调用 deinit。但是在我的应用程序上不是。然后可能会有一个强大的参考。我不明白为什么仪器/泄漏显示所有绿色检查..
      • 在将 A 导航到 B 时,我在 prepareForSegue 中“传递”了 2 个对象。 1 是一个自定义类。另一个是自定义类的数组。第一个我可以弱化,但后者我不能“只能应用于类和类绑定协议类型,而不是......”
      • 你可以为你准备一些代码吗 prepareForSegue ?它将帮助我们识别问题并为您提供帮助。还有你的自定义类的代码。
      • 我刚刚发现了问题。看起来原因是 ImageSlideshow pod。 github.com/zvonicek/ImageSlideshow。因为当我注释掉所有对它的引用时,我调用了 deninit 中的 print 方法。 github.com/zvonicek/ImageSlideshow/issues/154
      • 干得好!有时外部 API 会出现奇怪的行为。
      猜你喜欢
      • 2013-07-31
      • 2012-05-07
      • 2012-01-01
      • 2014-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      相关资源
      最近更新 更多