0

I have created a CustomAlertView.

protocol CustomAlertViewControllerDelegate{
    func retryToFetchData()
}

class CustomAlertViewController: UIViewController {

    @IBOutlet weak var alertView: UIView!
    var delegate: CustomAlertViewControllerDelegate!

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

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.alertView.alpha = 0
        self.alertView.frame.origin.y = self.alertView.frame.origin.y + 50

        UIView.animate(withDuration: 0.4) {
            self.alertView.alpha = 1.0
            self.alertView.frame.origin.y = self.alertView.frame.origin.y - 50
        }
    }


    @IBAction func retryButton(_ sender: UIButton) {
        delegate?.retryToFetchData()
        self.dismiss(animated: true, completion: nil)
    }

}

I have created a static function to show that view. The view is just a UIViewController that will have a child View which will act as a popUP, with a transparent background.

func showErrorBox(view: UIViewController, message: String, delegate: CustomAlertViewControllerDelegate){ 

    let customAlert = view.storyboard?.instantiateViewController(withIdentifier: "customAlertViewController") as! CustomAlertViewController
    customAlert.providesPresentationContextTransitionStyle = true
    customAlert.definesPresentationContext = true
    customAlert.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
    customAlert.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
    customAlert.delegate = delegate
    view.present(customAlert, animated: true, completion: nil)
}

Now, I am calling this VC anywhere I needed to show a popUP with showErrorBox(view: self, message: message, delegate: self) now my issue is I need to show this popup in a ViewController which is inside of a TabBarController, when I change the view between the UITabBar, and try pressing the reload button, the app throws an error,

presentViewController does not work: view is not in the window hierarchy

Edit: There is a Retry button on the ErrorBox(popUp). The error happens only when the error box is loaded and I changed the view to different tab and then hit the reload button. In normal scenario like, hitting the reload button when I am in the same page works fine.

I am not sure of issue, but it has something to do with when I change the view between tabs when the error box is present.

Asis
  • 545
  • 2
  • 16
  • where you call this Method `showErrorBox(view: self, message: message, delegate: self)` in viewDidload – Abdelahad Darwish Jun 04 '18 at 10:04
  • Please cross verify identifier – PPL Jun 04 '18 at 10:05
  • No I call that when Something goes wrong, may no internet available, or json parsing error, something like that. – Asis Jun 04 '18 at 10:19
  • This is normal behavior I think, the error is showing and you change tabbar controller, then you press retry, if error happened again, mean you are trying to present the error view again in the non-visible controller, thus the error happen, you should make the alert cover full screen to make user unable to change tab and dismiss the error first – Tj3n Jun 04 '18 at 10:55
  • The shown code does not illustrate the underlying problem. The error tells you that you are passing your `showErrorBox` method a view controller object that does not currently render its view on screen (that is ultimately meant by "not in the window hierarchy"). Also, please do not call a view controller "view", that's confusing. :) They're not the same thing, far from it. – Gero Jun 04 '18 at 11:07

3 Answers3

0

try self.present(customAlert, animated: true, completion: nil) instead view.present(customAlert, animated: true, completion: nil). If I understand your problem, should works

Achron
  • 107
  • 5
  • can describe why you might think so ? have you tried, or solved the similar issue with the similar answer ? – Asis Jun 04 '18 at 10:47
  • CustomAlertViewController is current view controller. If you try to open VC from other context, not in current NavigationController you will open it, but not show. That why if you present from self (currentViewController) with current NavigationBar that works better. Also you can choice different ways but you may go deeper, UIWindow if that an alert. PresentViewController for alerts is not best choice) – Achron Jun 04 '18 at 11:43
0

Solution,

The problem was, when I changed the views in TabController the reference to the customAlertView was removed from the window hierarchy. So, As soon as I leave the TabView which was loading the CustomAlertView need to be removed.

So to solve the issue, I have added following code in CustomAlertViewController

override func viewWillDisappear(_ animated: Bool) {
    super. viewWillDisappear(animated)
    self.dismiss(animated: true, completion: nil)
}
Asis
  • 545
  • 2
  • 16
-1

Try to getting the TopMost ViewController and presenting CustomAlertViewController from it instead of "self".

refer this link to : GetTopMostViewController

Santhosh
  • 134
  • 1
  • 8