Get the top ViewController in iOS Swift

I want to implement a separate ErrorHandler class that displays error messages for specific events. The behavior of this class must be called from various other classes. If an error occurs, it will have an output UIAlertView. The display of this AlertView should ALWAYS be on top. Thus, no matter where the error comes from, the top viewController should display AlertMessage (for example, if the asynchronous background process crashes, I want to get an error message, regardless of which view is displayed in the foreground).

I found several gists that seem to solve my problem (see code below). But the call UIApplication.sharedApplication().keyWindow?.visibleViewController()returns nil.

Gist extension

extension UIWindow {
func visibleViewController() -> UIViewController? {
if let rootViewController: UIViewController  = self.rootViewController {
  return UIWindow.getVisibleViewControllerFrom(rootViewController)
}
return nil
}

class func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController {

if vc.isKindOfClass(UINavigationController.self) {

  let navigationController = vc as! UINavigationController
  return UIWindow.getVisibleViewControllerFrom( navigationController.visibleViewController)

} else if vc.isKindOfClass(UITabBarController.self) {

  let tabBarController = vc as! UITabBarController
  return UIWindow.getVisibleViewControllerFrom(tabBarController.selectedViewController!)

} else {

  if let presentedViewController = vc.presentedViewController {

    return UIWindow.getVisibleViewControllerFrom(presentedViewController.presentedViewController!)

  } else {

    return vc;
  }
}
}
}
+4
2

Amit89 . .window AppDelegate. Swift , ViewController. , . .viewDidLoad

, ViewController *

extension UIApplication {
  class func topViewController(base: UIViewController? = (UIApplication.sharedApplication().delegate as! AppDelegate).window?.rootViewController) -> UIViewController? {
    if let nav = base as? UINavigationController {
      return topViewController(base: nav.visibleViewController)
    }
    if let tab = base as? UITabBarController {
      if let selected = tab.selectedViewController {
        return topViewController(base: selected)
      }
    }
    if let presented = base?.presentedViewController {
      return topViewController(base: presented)
    }
    return base
  }
}

GitHub Yonat . , .keyWindow

+20

?

let appDelegate = UIApplication.sharedApplication().delegate as! MYAppDelegate//Your app delegate class name.


extension UIApplication {
    class func topViewController(base: UIViewController? = appDelegate.window!.rootViewController) -> UIViewController? {
        if let nav = base as? UINavigationController {
            return topViewController(base: nav.visibleViewController)
        }
        if let tab = base as? UITabBarController {
            if let selected = tab.selectedViewController {
                return topViewController(base: selected)
            }
        }
        if let presented = base?.presentedViewController {
            return topViewController(base: presented)
        }
        return base
    }
}
+1

All Articles