简体   繁体   English

导航堆栈中的ViewController在弹出时不会消失,导致内存泄漏

[英]ViewController in navigation stack won't deinit when popped, causing memory leak

In my app I have a RootViewController which all my ViewControllers are subclassed from. 在我的应用程序中,我有一个RootViewController ,我的所有ViewControllers都是子类。 When developing, I usually use this in my RootVC: 开发时,我通常在RootVC中使用它:

deinit { 
    print("\(type(of: self)) deinit")
}

so that I always can see when any of my viewControllers deinit. 这样我能看到我的任何viewControllers何时出现。 It prints: 它打印:

MyExampleViewController deinit MyExampleViewController deinit

Today I noticed that one of them didn't deinit when I navigated away from it. 今天我注意到当我离开它时,其中一个没有离开。 Let's call it DetailViewController . 我们称之为DetailViewController It's a completely normal (Root)ViewController-subclass pushed into the main NavigationController . 这是一个完全正常的(Root)ViewController子类,被推入主NavigationController When hitting the Back button in the navigation, it navigates away, but never says it deinits. 当点击导航中的Back button时,它会导航,但从不说它会消失。 This is the first pushed controller, so I can't pop the controller before to see if that helps. 这是第一个推送控制器,所以我不能在之前弹出控制器,看看是否有帮助。 But any controller pushed after the DetailViewController gets deinited fine when navigating back and forth. 但是DetailViewController来回导航时,任何控制器都会被推动。

I decided to check the memory graph, so I ran my app again, pushed to the DetailViewController , then popped it away by clicking the Back button in the navigation, then I clicked Debug memory graph . 我决定检查内存图,所以我再次运行我的应用程序,推送到DetailViewController ,然后单击导航中的Back button将其弹出,然后单击Debug memory graph

In the debug navigator on the left, I scroll down and see that there exists one instance of my DetailViewController . 在左侧的调试导航器中,我向下滚动,看到我的DetailViewController存在一个实例。 If I push back and forth several times before opening the memory graph, there are as many different instances of this DetailViewController as times I've pushed and popped. 如果我在打开内存图之前来回移动几次,那么当我推送和弹出时,这个DetailViewController实例就会多。

When clicking it, I see this: 点击它,我看到这个:

记忆图 The DetailViewController is the single controller on the far right. DetailViewController是最右侧的单个控制器。 I haven't used Memory Graph that much, but I assume that the "solid" white lines are strong claims, and that the slightly more transparent (gray) lines are weak claims. 我没有那么多使用Memory Graph ,但我认为“实心”白线是强烈的主张,而稍微更透明(灰色)的线是弱主张。 Meaning that there's one strong claim to my controller. 这意味着我的控制器有一个强烈的主张。 The one on the bottom. 底部的那个。

This is the bottom row: 这是底行: 记忆图2

What does this mean? 这是什么意思? It seems like my (custom) NavigationController has an array called _childViewControllers which retains my popped controller. 看起来我的(自定义) NavigationController有一个名为_childViewControllers的数组,它保留了我的弹出控制器。 To clarify, I don't have any stored variables in my custom NavigationController . 为了澄清,我的自定义NavigationController没有任何存储的变量。 It's only subclassed to override 5 functions, that is all. 它只是覆盖5个函数的子类,就是全部。 I have about 20 different ViewControllers being pushed and popped by this exact same custom `NavigationController, but they all have no problem with this. 我有大约20个不同的ViewControllers被这个完全相同的自定义`NavigationController推送和弹出,但它们都没有问题。

Am I reading the graph wrong? 我读图错了吗? There has to be a different strong claim that's not visible in the graph, right? 必须有一个不同的强烈主张,在图表中不可见,对吗? When I "pop" the viewController by clicking Back , shouldn't my viewController be removed by _childViewControllers ? 当我“啪”的viewController通过单击Back ,应该不是我viewController被移除_childViewControllers

Figured it out at last. 终于搞清楚了。 Unfortunately, I had to go through commenting out several hundred lines of code bit by bit until I found out when it started to deinit when expected. 不幸的是,我不得不一点一点地评论几百行代码,直到我发现它何时开始在预期时去掉。 The issue was a missing [weak self] in a closure, not unexpected, but it was in a completely different class, connected through a complicated hierarchy. 问题是在一个闭包中缺少[weak self] ,并不出乎意料,但它是在一个完全不同的类中,通过复杂的层次结构连接起来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 UINavigationController:弹出时释放ViewController的内存 - UINavigationController: Release ViewController's memory when popped 与 Deinit 和内存泄漏混淆 - Confused with Deinit and Memory leak Coredata内存泄漏:未调用Deinit ..导致内存泄漏 - Coredata memory leak: Deinit does not get called.. causing memory leak 移动ViewController时,标签栏和导航栏不会显示 - Tab Bar and Navigation Bar won’t show when the ViewController is moved 从导航堆栈中弹出视图时,为什么键盘不显示? - Why does the keyboard not show when a view is popped from the navigation stack? 如何从导航堆栈中推送/弹出uiviewcontroller时收到警报 - How to be alerted when uiviewcontroller is pushed / popped from navigation stack UICollectionView调用scrollViewDidScroll:从导航堆栈弹出时 - UICollectionView calling scrollViewDidScroll: when popped from the navigation stack 从Xamarin.iOS的导航堆栈中弹出ViewController后不会释放 - ViewController is not getting released after being popped from navigation stack in Xamarin.iOS 推入导航堆栈时隐藏 TabBar 并在弹出导航堆栈时将其带回来 - Hide TabBar when pushed into the navigation stack and bring it back when popped out of the navigation stack ViewController 内存泄漏 - Memory Leak in ViewController
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM