David
David

Reputation: 3318

Present alert after dismissing View Controller

I'm using the newest Xcode and Swift version.

I'm presenting a specific View Controller like this:

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let contactViewController = storyboard.instantiateViewController(identifier: "contactViewController")
show(contactViewController, sender: self)

I'm dismissing this View Controller like this:

self.presentingViewController?.dismiss(animated: true, completion: nil)

I want to present an UIAlertController right after dismissing the View Controller.

This:

self.presentingViewController?.dismiss(animated: true, completion: nil)

let alertMessage = UIAlertController(title: "Your message was sent", message: "", preferredStyle: .alert)
let alertButton = UIAlertAction(title: "Okay", style: UIAlertAction.Style.default)
alertMessage.addAction(alertButton)
self.present(alertMessage, animated: true, completion: nil)

… of course doesn't work because I cannot present an UIAlertController on a dismissed View Controller.

What's the best way to present this UIAlertController after the View Controller is dismissed?

Upvotes: 0

Views: 1835

Answers (2)

Zhou Haibo
Zhou Haibo

Reputation: 2068

Use Jawad Ali's extension, we could anchor the current presented ViewController.

And if you want to dismiss that alert later, you could do it in another completion handler as below code showed. In my case, I save a song to one playlist and dismiss this playlist and show a short time alert to let user know that saving ok.

DispatchQueue.main.async {
    self?.removeSpinner()
    self?.dismiss(animated: true, completion: {
        let alert = UIAlertController(title: "Save to playlist", message: nil, preferredStyle: .alert)
        UIApplication.getTopMostViewController()?.present(alert, animated: true, completion: {
            Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { _ in
                alert.dismiss(animated: true)
            }
        })
    })
}               

Upvotes: 0

Jawad Ali
Jawad Ali

Reputation: 14397

You can do it in completion handler by getting top controller like this

self.presentingViewController?.dismiss(animated: true, completion: {
            let alertMessage = UIAlertController(title: "Your message was sent", message: "", preferredStyle: .alert)
               let alertButton = UIAlertAction(title: "Okay", style: UIAlertAction.Style.default)
               alertMessage.addAction(alertButton)
            UIApplication.getTopMostViewController()?.present(alertMessage, animated: true, completion: nil)
        })

Using this extension

extension UIApplication {

    class func getTopMostViewController() -> UIViewController? {
        let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
        if var topController = keyWindow?.rootViewController {
            while let presentedViewController = topController.presentedViewController {
                topController = presentedViewController
            }
            return topController
        } else {
            return nil
        }
    }
}

Upvotes: 4

Related Questions