Reputation: 8503
In my app I have a RootViewController
which all my ViewControllers are subclassed from. When developing, I usually use this in my RootVC:
deinit {
print("\(type(of: self)) deinit")
}
so that I always can see when any of my viewControllers deinit. It prints:
MyExampleViewController deinit
Today I noticed that one of them didn't deinit when I navigated away from it. Let's call it DetailViewController
. It's a completely normal (Root)ViewController-subclass pushed into the main NavigationController
. When hitting the Back button
in the navigation, it navigates away, but never says it deinits. 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.
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.
In the debug navigator on the left, I scroll down and see that there exists one instance of my 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.
When clicking it, I see this:
The
DetailViewController
is the single controller on the far right. 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. Meaning that there's one strong claim to my controller. The one on the bottom.
What does this mean? It seems like my (custom) NavigationController
has an array called _childViewControllers
which retains my popped controller. To clarify, I don't have any stored variables in my custom NavigationController
. It's only subclassed to override 5 functions, that is all. I have about 20 different ViewControllers
being pushed and popped by this exact same custom `NavigationController, but they all have no problem with this.
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
?
Upvotes: 1
Views: 2273
Reputation: 8503
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.
Upvotes: 4