0
votes

I have two ViewControllers (ViewController is the first; SecondViewController is the second) embedded in a Navigation Controller.

On ViewController, there is a NotificationCenter observer in viewDidLoad.

On SecondViewController, I have a button that should post a notification to ViewController that will trigger a UIAlertController when it appears again.

ViewController:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        addObservers()
    }

    func addObservers(){
        NotificationCenter.default.addObserver(self, selector: #selector(alertThankYou), name: Notification.Name(rawValue: Constants.handleThankYouNotif), object: nil)
    }
    func removeObservers(){
        NotificationCenter.default.removeObserver(self, name: Notification.Name(rawValue: Constants.handleThankYouNotif), object: nil)
    }

    @objc func alertThankYou(notification: Notification) {
        self.view.backgroundColor = .red
        let alertController = UIAlertController(title: "THANK YOU", message: "lorem ipsum dolor sit amet.", preferredStyle: .alert)
        let okAction = UIAlertAction(title: "Done", style: UIAlertAction.Style.default) { (result : UIAlertAction) -> Void in
            print("done pressed")
        }
        alertController.addAction(okAction)
        self.present(alertController, animated: true, completion: nil)
    }

    deinit {
        removeObservers()
    }

}

SecondViewController:

class SecondViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    // Press this first to post the Notification!
    @IBAction func TRIGGERPOSTPRESSED(_ sender: UIButton) {
        NotificationCenter.default.post(name: Notification.Name(Constants.handleThankYouNotif), object: nil)
    }

    // Then press this to return back to ViewController to HOPEFULLY see an Alert.
    @IBAction func close(_ sender: Any) {
        if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
            appDelegate.window?.rootViewController?.dismiss(animated: true, completion: nil)
            (appDelegate.window?.rootViewController as? UINavigationController)?.popToRootViewController(animated: false)
        }
    }

}

The problem: On SecondViewController, when TRIGGERPOSTPRESSED is pressed, I get this warning in console:

Warning: Attempt to present UIAlertController on ViewController whose view is not in the window hierarchy!

What should happen: On SecondViewController, when TRIGGERPOSTPRESSED is pressed, I should not get any errors. Then when close is pressed and the App returns back to ViewController, i should get the alert!

How can I achieve this with NotificationCenter?

2

2 Answers

0
votes

I Think you should not use NotificationCenter, in this case, you should use Delegates Protocol Pattern as in this previous question about Notification Center vs. Delegation in iOS SDK and of course this not the issue producer but it's the right practice to use Delegation when you need only tow classes to communicate.

0
votes

Please post the notification on completion while dismissing the SecondViewController. The code snippet:

@IBAction func close(_ sender: Any) {
    if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
        appDelegate.window?.rootViewController?.dismiss(animated: true, completion: {
            NotificationCenter.default.post(name: Notification.Name(handleThankYouNotif), object: nil)
        })
        (appDelegate.window?.rootViewController as? UINavigationController)?.popToRootViewController(animated: false)
    }
}

The alert pop up