导航控制器后退按钮未释放被解除的viewController

时间:2017-11-14 15:17:42

标签: ios swift memory-leaks uiviewcontroller

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

使用IB执行所有操作,我从collectionView单元格项目ctrl-dragged到B并选择' show(例如Push)' Segue公司。

现在,当我运行应用程序并在网格中的图像上多次单击,然后在'<回'按钮,我探索内存图。 我可以看到10' B'如果我进行了10次导航,请查看控制器。

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

我发现了一些关于放松的帖子,并且弹出到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 = ""

3 个答案:

答案 0 :(得分:1)

为避免保留被解雇的VC内存,您需要检查是否有任何保留周期。

帮助您检查您的VC是否已正确取消初始化的一步,您可以实施一个名为deinit的方法。它是一种在VC退出并且不再存储在内存中时调用的方法。您可以打印一条消息,看看是否属实。

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

答案 1 :(得分:0)

  1. 与UI元素(在视图控制器中)的所有IB连接必须是weak
  2. 尝试在strong方法中发布dealloc个对象;
  3. 有时在垃圾收集器解除分配对象之前会有一些延迟,请执行" show"并且"返回",等待~10秒,看看是否释放了更多内存。

答案 2 :(得分:0)

作为@ 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后,我的保留周期消失了。