UIAlertController not disappearing


Answers

If we create a new "single view" project For the the following two ways of presenting the alert we get the following behaviors

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let alertController = UIAlertController(title: "Wrong Item", message: "Could not find details of an item.", preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        present(alertController, animated: true, completion: nil)
    }

In the console you will see

2017-08-15 16:27:35.871 test[66719:7754741] Warning: Attempt to present on whose view is not in the window hierarchy!

and no alert on the UI.

and for:

   override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        let alertController = UIAlertController(title: "Wrong Item", message: "Could not find details of an item.", preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        present(alertController, animated: true, completion: nil)
    }

every thing works as expected.

So yes, view did appear is the place.

About viewDidLoad() and viewDidAppear(_:)

From the looks of it the problem lies with beginIgnoringInteractionEvents

If you are putting your alert on viewDidAppear you should see it but if you don't see it, please note the following:

Even if you put this piece of code in viewdidload

        DispatchQueue.main.async {

            self.activityIndicator.stopAnimating()
            UIApplication.shared.endIgnoringInteractionEvents()

            //Other UI update operation

        }

it may get executed later (depends on when the parsing finishes) than the call of viewDidAppear and this is because:

DispatchQueue.global(qos: .background).async

Did you check this reason?

Question

I am not getting what's wrong with my code. I am simply displaying an alert with "Ok" button and when user click on "Ok", then alert should go. But its not getting disappeared. Using Swift3 for programming. Is viewDidAppear() right place to put this code? Or am I doing something wrong?

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    let alertController = UIAlertController(title: "Wrong Item", message: "Could not find details of an item.", preferredStyle: .alert)          
    alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
    present(alertController, animated: true, completion: nil)  
}

UPDATE: When I put the same code in other controller, it worked. In original controller, in viewDidLoad(), I have an Async call like below. Is this problem because of that?

DispatchQueue.global(qos: .background).async {
    self.getDetails(onCompletion: {(json: JSON) in

    let dict = self.convertToDictionary(text: json.stringValue)

        DispatchQueue.main.async {

            self.activityIndicator.stopAnimating()
            UIApplication.shared.endIgnoringInteractionEvents()

            //Other UI update operation

        }
    })
}    

I also override viewWillDisappear() and viewWillAppear(), just to set Title of Screen.




'UIAlertView' was deprecated in iOS 9.0. Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead

Reference UIAlertController

See this Code Destructive and OK buttons in UIAlertController:

let alertController = UIAlertController(title: "Destructive", message: "Simple alertView demo with Destructive and Ok.", preferredStyle: UIAlertControllerStyle.alert) //Replace UIAlertControllerStyle.Alert by UIAlertControllerStyle.alert
let DestructiveAction = UIAlertAction(title: "Destructive", style: UIAlertActionStyle.Destructive) {
    (result : UIAlertAction) -> Void in
    print("Destructive")
}

// Replace UIAlertActionStyle.Default by UIAlertActionStyle.default
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
    (result : UIAlertAction) -> Void in
    print("OK")
}

alertController.addAction(DestructiveAction)
alertController.addAction(okAction)
self.presentViewController(alertController, animated: true, completion: nil)

Swift 3:

let alertController = UIAlertController(title: "Destructive", message: "Simple alertView demo with Destructive and Ok.", preferredStyle: UIAlertControllerStyle.alert) //Replace UIAlertControllerStyle.Alert by UIAlertControllerStyle.alert

let DestructiveAction = UIAlertAction(title: "Destructive", style: UIAlertActionStyle.destructive) {
                        (result : UIAlertAction) -> Void in
    print("Destructive")
}

                    // Replace UIAlertActionStyle.Default by UIAlertActionStyle.default

let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
                        (result : UIAlertAction) -> Void in
    print("OK")
}

alertController.addAction(DestructiveAction)
alertController.addAction(okAction)
self.present(alertController, animated: true, completion: nil)

See Alert With Destructive and OK Button:




For a basic alert message I like using an extension on UIViewController:

extension UIViewController {
func alertMessageOk(title: String, message: String) {
    let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
    let action = UIAlertAction(title: "Ok", style: .default, handler: nil)
    alert.addAction(action)
    present(alert, animated: true, completion: nil)
   }
}

Usage: self.alertMessageOk(title: "Test Title", message: "Test message")







Tags