2

My scenario, I am trying to create Loader within AlertViewController. Here, I am getting below warnings and not allowing to dismiss after two trials. I am using below function in a common class and reusing in multiple viewController.

My Code

    // MARK: Common AlertView
        extension UIViewController {

            func loadinHubShow() {

                    let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
                    let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
                    loadingIndicator.hidesWhenStopped = true
                    loadingIndicator.style = UIActivityIndicatorView.Style.gray
                    loadingIndicator.startAnimating();
                    alert.view.addSubview(loadingIndicator)
                    present(alert, animated: true, completion: nil)
                }

                func loadinHubDismiss() {
                    dismiss(animated: false, completion: nil)
                }
        }

Other ViewController

    func dataJson() {

 // Start Loading
    self.loadinHubShow()

// after process done
 DispatchQueue.main.async {
         self.loadinHubDismiss()
    }
}

My Warning

Warning: Attempt to dismiss from view controller while a presentation or dismiss is in progress!

jackios
  • 155
  • 2
  • 11

2 Answers2

1

As I see, you're using this functions as UIViewController extension.

One way to achieve you're result is to get a reference to the alert you're using.

NOTE: If you use dismiss function as you did, you're trying to dismiss the viewController, not the alert, that's why you're getting that warning.

Try to change your extension function this way:

1) loadinHubShow will return a reference to the alert

      func loadinHubShow() -> UIAlertController {

            let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
            let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
            loadingIndicator.hidesWhenStopped = true
            loadingIndicator.style = UIActivityIndicatorView.Style.gray
            loadingIndicator.startAnimating();
            alert.view.addSubview(loadingIndicator)

            return alert
            //You don't have to present the alert here
            //present(alert, animated: true, completion: nil)
        }

2) loadinHubDismiss will remove that alert:

         func loadinHubDismiss(alert: UIAlertController) {
            alert.dismiss(animated: false, completion: nil)
        }

In order to use these function, let's assume you have your ViewController:

            class ViewController: UIViewController{

              var myAlert: UIAlertController = UIAlertController()

               override func viewDidLoad(...){
                  myAlert = self.loadinHubShow()
                  //now you can present or dismiss the alert wherever you want
                  //for example:
                  self.present(myAlert,animated: false, completion: nil)

                  //when you want dismiss the alert, just call:
                  self. loadinHubDismiss(alert: myAlert)
               }



            }

EDIT

to dismiss the alert, as suggested, try:

   DispatchQueue.main.async{
        loadinHubDismiss(alert: myAlert)
   }
Andrew21111
  • 868
  • 8
  • 17
0

The problem is related to that you do a synchronous json parsing process which causes

  func dataJson() { 
      self.loadinHubShow()

   // after process done
   DispatchQueue.main.async {
     self.loadinHubDismiss()
    }
 }

the alert to dismiss before it's done showing hence the warning , so either completely remove the alert waiting or use dispatchAfter

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
   self.loadinHubDismiss()
}
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87