UIAlertAction handler/closure does not execute

I have an UIViewController extension which I am using to display alerts in any view controller. It worked fine until this weird use case happened:

extension UIViewController {
    func showModal(title: String, msg: String, handler: ((UIAlertAction) -> Void)? = nil) {
        let alert = UIAlertController(title: title, message: msg, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: handler))
        DispatchQueue.main.async {
            self.present(alert, animated: true, completion: nil)
        }
    }
}

Inside a view controller I tap a button which triggers a network fetch:

@IBAction func didTapSave(_ sender: UIButton) {

Task {
    
    let result = await BalanceManager.shared.fetchAllBalances()
    
    switch result {
    case .success(_):
        self.showModal(title: "", msg: "account successfully saved") { (_) in
            //This code always gets executed
            self.navigationController?.popViewController(animated: true)
        }
    case .failure(let failure):
        self.showModal(title: "", msg: "failure") { (_) in
            //Code in here is not executed
            print("Failure closure")
        }
    }
}

I don't understand why on case ".failure" the closure for showModal does not execute. If I set a breakpoint on the line with self.showModal the code gets there but does not execute the closure when I tap "OK" on the popup

So the alert is called, proving that showModal() is executed in case of failure ?

Could you replace

            self.navigationController?.popViewController(animated: true)

by a simple print, just for test ?

Accepted Answer

I figured it out, it was my programming mistake and lack of proper sleep :). Another VC which was listening for notifications about the result of the same fetch was triggering a popup even though it was not visible, but was alive, embedded in a tab bar controller. So my "failure" popup was never executed properly. I figured it out after I updated the showModal method with the sender parameter and following that I have added a fix that requires the calling VC to be visible when it wants to present a popup:

func showModal(sender: UIViewController, title: String, msg: String, handler: ((UIAlertAction) -> Void)? = nil) {
    let alert = UIAlertController(title: title, message: msg, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: handler))
    DispatchQueue.main.async {
      if sender.isVisible() {
        self.present(alert, animated: true, completion: nil)
      }
    }
  }

where isVisible():

extension UIViewController {
  func isVisible() -> Bool {
    return self.isViewLoaded && self.view.window != nil
  }
}
UIAlertAction handler/closure does not execute
 
 
Q