1

In my project, I am using rootViewController?.dismiss to dismiss some View Controllers back to the main VC.

In the completion handler, I would like to present a UIAlertController on the main View Controller once it becomes visible again.

My problem is the UIAlertController never appears. My hunch is because I'm using self in the launchFrom parameter. Do I need to get a reference back to the main VC, and present it there?

Dismiss VC and try presenting Alert:

self.view.window!.rootViewController?.dismiss(animated: false, completion: {
    Constants.presentThankYou(launchFrom: self)
})

presentThankYou method

static func presentThankYou(launchFrom: UIViewController) {
    let alertController = UIAlertController(title: "Thank You!", message: "You did it!", preferredStyle: UIAlertControllerStyle.alert)
    let okAction = UIAlertAction(title: "Close", style: UIAlertActionStyle.default) { (result : UIAlertAction) -> Void in
        print("Done")
    }
    alertController.addAction(okAction)
    launchFrom.present(alertController, animated: true, completion: nil)
}

How do I present the Alert Controller after all of my VC's have been dismissed?

Joe
  • 3,772
  • 3
  • 33
  • 64
  • Just call the alert in controller that will become as parentView after you dismissed the required controller use a struct bool that can be accessed globally and check that bool value and show alert when required – iOS Geek Dec 19 '17 at 04:47

4 Answers4

3

Out of my head, Try doing it in viewDidAppear. To prevent the alert from showing up all the time, use a bool shouldShowThankYouAlert and set this value to true in the dismiss completion handler

Mugunth
  • 14,461
  • 15
  • 66
  • 94
1

You can also refer to this if required , Just call the alert to show in viewWillDisappear of Controller that is being dismissed

override func viewWillDisappear(_ animated: Bool) {
        if self.isMovingFromParentViewController {
            DispatchQueue.main.async {
                wrapperClass.BasicAlert("View is Dismissed", message: "", view: self)
            }
        }
    }

This will show Alert when view is dismissed Fully

iOS Geek
  • 4,825
  • 1
  • 9
  • 30
0

I did not check that but how about using window instead of UIViewController.

self.view.window!.rootViewController?.dismiss(animated: false, completion: {
   Constants.presentThankYou()
})

static func presentThankYou() {
   let alertController = UIAlertController(title: "Thank You!", message: "You did it!", preferredStyle: UIAlertControllerStyle.alert)
   let okAction = UIAlertAction(title: "Close", style: UIAlertActionStyle.default) { (result : UIAlertAction) -> Void in
       print("Done")
    }
   alertController.addAction(okAction)
   appDelegate.window.present(alertController, animated: true, completion: nil)
}
Prabhjot Singh Gogana
  • 1,408
  • 1
  • 14
  • 39
-1

So one problem, a completion block doesn't require the main-thread. I suggest forcing the completion to execute some code.

var topController: UIViewController? {
  if var temp = UIApplication.shared.keyWindow?.rootViewController {
    while let presentedViewController = temp.presentedViewController {
      temp = presentedViewController
    }
    return temp
  }
  return nil
}

self.view.window!.rootViewController?.dismiss(animated: false, completion: {
  DispatchQueue.main.async {
    guard let top = topController else { return }
    Constants.presentThankYou(launchFrom: top)
  }
})
jnblanchard
  • 1,182
  • 12
  • 12
  • @AndreaMugnaini According to my tests, self exists in many cases and will likely be a fine answer for this question. – jnblanchard Dec 19 '17 at 00:29
  • I tried to replicate the Joe's scenario described above, and I am crashing with your previous code. Since the view controller supposed to be the pivot of the alert controller is going to be deallocated. Although in your case, might be working, I think is safer to don't take assumptions on an "unknown" `presentedViewController` – mugx Dec 19 '17 at 00:33
  • uhh you're doing something wrong if you're crashing with the first answer I submitted. I made this answer dummy proof. – jnblanchard Dec 19 '17 at 00:51
  • Maybe. But you might try by yourself: open a `fresh new` project, make a navigation with just 2 view controllers, push vc2 from vc1, pop back from vc2, see what happens. Your code was this (put it in vc2): `override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) self.view.window!.rootViewController?.dismiss(animated: false, completion: { DispatchQueue.main.async { ViewController2.presentThankYou(launchFrom: self) } }) }` – mugx Dec 19 '17 at 00:56
  • Of course this wont work... you just dismissed that same vc – jnblanchard Dec 19 '17 at 01:00
  • Yes, exactly. So your solution (which I used sometimes in the past) won't work for all the cases. – mugx Dec 19 '17 at 01:01
  • Yes I agree with you, my solution won't work if you apply it poorly. That's why I updated my answer. Thank you. – jnblanchard Dec 19 '17 at 01:02