0

I created two view controllers like

Navigation controller -> View Controller -> Details View Controller
          1                     2                      3

The (2) View Controller has a button in it which when clicked will shows (3) Details View Controller. I have created a segue from button to (3) VC.

I have added deinit blocks in those two classes.

deinit {
    print("vc deinit")
}

However, this does not get logged. When will a view controller get deallocated?

Sample code

John Doe
  • 2,225
  • 6
  • 16
  • 44
  • Related (Duplicate?): https://stackoverflow.com/questions/26971415/deinit-never-called – Ahmad F Mar 17 '19 at 15:20
  • None of the provided solutions answer this question. – John Doe Mar 17 '19 at 15:21
  • Possibly useful: https://stackoverflow.com/questions/41772225/explanation-for-deinit-not-called?rq=1 – Ahmad F Mar 17 '19 at 15:23
  • 1
    Is there any special code that might leads to a retain cycle in the view controllers? – Ahmad F Mar 17 '19 at 15:26
  • I have add the sample project to the question. – John Doe Mar 17 '19 at 15:29
  • Project won't work (no pods exist). However, make sure that the details view controller is connected to `DetailsViewController` class in the interface builder, therefore when tapping back, you should see "details vc deinit" logged. – Ahmad F Mar 17 '19 at 15:31
  • Please delete all the pods. I have updated the zip. – John Doe Mar 17 '19 at 15:34
  • Thanks. That works. When switching to details, why is the previous VC not getting deallocated? – John Doe Mar 17 '19 at 15:38
  • 1
    @jsloop: Your first sketch shows the reason: The navigation controller holds a reference to the first VC. – Martin R Mar 17 '19 at 15:42
  • @jsloop: More precisely: UINavigationController holds references to *all* VCs in the current navigation stack, via its `viewControllers` property. – Martin R Mar 17 '19 at 15:48
  • @MartinR even without a UINavigationController (let's say present/dismiss), the initial view controller won't get deallocated since its the root view controller... Please correct me if I'm wrong. – Ahmad F Mar 17 '19 at 16:01
  • 1
    @AhmadF: The root view controller is the navigation controller in this case. But yes, this was just a comment, not intended to cover all possible situations. – Martin R Mar 17 '19 at 16:20

1 Answers1

3

In this case, the only deinit will get called is the second one (the one implemented in the Details View Controller) each time you tap the back button on the navigation (pop to the previous view controller).

So, why the first deinit (the one in the View Controller) didn't get called?

That's because it is the first view controller in the navigation controller stack. Pushing to the second view controller does not mean that the previous one(s) one has been deallocated and still exists as the first element in the navigation stack; As an example, that's why viewDidLoad method should not get called when you come back from a popped view controller, which means it did not get deallocated.

Ahmad F
  • 30,560
  • 17
  • 97
  • 143