UIViewController memory leak with modal presentedViewController

Hi everyone,

I'm encountering an unexpected behavior with modal presentations in UIKit. Here’s what happens:

  • I have UIViewControllerA (let’s call it the "orange" VC) pushed onto a UINavigationController stack.
  • I present UIViewControllerB (the "red" VC, inside its own UINavigationController as a .formSheet) modally over UIViewControllerA.
  • After a short delay, I pop UIViewControllerA from the navigation stack.

Issue:

  • After popping UIViewControllerA, the modal UIViewControllerB remains visible on the screen and in memory. I expected that dismissing (popping) the presenting view controller would also dismiss the modal, but it stays.

Expected Behavior:

  • When UIViewControllerA (orange) is popped, I expect the modal UIViewControllerB (red) to be dismissed as well.

Actual Behavior:

  • The modal UIViewControllerB remains on screen and is not dismissed, even though its presenting view controller has been removed from the navigation stack.
  • Video example: https://youtube.com/shorts/sttbd6p_r_c

Question:

  • Is this the expected behavior? If so, what is the recommended way to ensure that the modal is dismissed when its presenting view controller is removed from the navigation stack?

Code snippet:

class MainVC: UIViewController {
  private weak var orangeVC: UIViewController?
  override func viewDidLoad() {
    super.viewDidLoad()
    self.view.backgroundColor = .blue
    let dq = DispatchQueue.main
    dq.asyncAfter(deadline: .now() + 1) { [weak self] in
      let vc1 = UIViewController()
      vc1.view.backgroundColor = .orange
      vc1.modalPresentationStyle = .overCurrentContext
      self?.navigationController?.pushViewController(vc1, animated: true)
      self?.orangeVC = vc1
      dq.asyncAfter(deadline: .now() + 1) { [weak self] in
        let vc2 = UIViewController()
        vc2.view.backgroundColor = .red
        vc2.modalPresentationStyle = .formSheet
        vc2.isModalInPresentation = true
        let nav = UINavigationController(rootViewController: vc2)
        if let sheet = nav.sheetPresentationController {
          sheet.detents = [.medium()]
        }
        self?.orangeVC?.present(nav, animated: true)
        dq.asyncAfter(deadline: .now() + 1) { [weak self] in
           self?.navigationController?.popViewController(animated: true)
        }
      }
    }
  }
}

Thank you for your help!

UIViewController memory leak with modal presentedViewController
 
 
Q