0

I am having trouble presenting a CustomAlert, subclass of UIViewController, from a UINavigationController stack view. To be more descriptive, I have a UITabBarController that wraps a UINavigationController. navController, has a rootView and a another pushed to the stack view, leafView of type UITableViewController. From leafView, I would like to present an alertView of type UIViewController which is transparent for the most part and with a opaque view inside. The problem is that when presenting, the background of this alertView is no longer transparent, but black, and upon dismissal it does not return to the leaf controller, but to the rootView. I think I am not presenting my alert from the correct view. How should I fix this?

searchController.present(friendAlert, animated: false, completion: nil)
dre_84w934
  • 678
  • 8
  • 27

1 Answers1

3

For alerts, it is much easier to present them from the "top view controller" instead of searching for the responsible controller in your hierarchy. A genius solution to find the controller is shown in this answer:

extension UIApplication {

    class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let navigationController = controller as? UINavigationController {
            return topViewController(controller: navigationController.visibleViewController)
        }
        if let tabController = controller as? UITabBarController {
            if let selected = tabController.selectedViewController {
                return topViewController(controller: selected)
            }
        }
        if let presented = controller?.presentedViewController {
            return topViewController(controller: presented)
        }
        return controller
    }

}

You can then show your alert from anywhere and after dismissing your alert you will get right back to the current view controller:

    DispatchQueue.main.async {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in }))
        UIApplication.topViewController()?.present(alert, animated: true, completion: nil)
    }
sundance
  • 2,930
  • 1
  • 20
  • 25
  • i like your approach. It kinda works, in the sense that now I can definitely see my UIViewController based alert starting to overlap the navigation controller and show the alert view from within. However it still goes back to a black background rather than a transparent one, and upon return i still get the rootview of the uinavigationcontroller. – dre_84w934 Jan 31 '18 at 22:17