0

This is my code. I don't understand why deinit is not called.

class SplashVC: UIViewController {
    init() {
        super.init(nibName: nil, bundle: nil)
        print("SplashVC created")
    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
            self?.navigationController?.popViewController(animated: false)
            self?.navigationController?.pushViewController(SignupViewController(), animated: true)
        }
    }
    deinit {
        print("SplashVC free")
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
Ricardo
  • 7,921
  • 14
  • 64
  • 111
  • Sorry If I don't understand well. I'm using `self?.navigationController?.popViewController` – Ricardo Oct 10 '19 at 09:42
  • Use [the method described here](https://stackoverflow.com/questions/41660486/knowing-where-retain-cycles-are-and-removing-them/41661291#41661291) to find out what is keeping a reference to your VC object. – Sweeper Oct 10 '19 at 09:43
  • Uh, creating an animation from the initializer is ugly. Also note that you can replace the controllers in the navigation stack directly, you don't need to pop. – Sulthan Oct 10 '19 at 09:45

3 Answers3

4

I read the documentations and now I know that pop root view controller was my problem.

This method removes the top view controller from the stack and makes the new top of the stack the active view controller. If the view controller at the top of the stack is the root view controller, this method does nothing. In other words, you cannot pop the last item on the stack

Ricardo
  • 7,921
  • 14
  • 64
  • 111
3

Probably your SplashVC is the root view controller in your navigation controller. If this is indeed the case, use this code instead:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
        self?.navigationController?.setViewControllers([SignupViewController()], animated: true)
    }
}
Yonat
  • 4,382
  • 2
  • 28
  • 37
1

The deinit method is not called because memory allocated for SplashVC is not freed.

You're simply pushing another UIViewController on the UINavigationController. The UINavigationController still stores all view controllers you have pushed to it, hence the memory allocated for each view controller is still allocated

You used the weak self as a measure to ensure there is no memory leak or retain cycle, but the deninit method in this case will only be called when SplashVC is popped from its UINavigationController. Until you pop the view controller, the memory allocated will still remain allocated and unavailable for other use.

Suh Fangmbeng
  • 573
  • 4
  • 16