获取 iOS Swift 中的顶级 ViewController [英] Get the top ViewController in iOS Swift

查看:38
本文介绍了获取 iOS Swift 中的顶级 ViewController的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现一个单独的 ErrorHandler 类,它在某些事件上显示错误消息.这个类的行为应该从不同的其他类中调用.当发生错误时,它会有一个 UIAlertView 作为输出.此 AlertView 的显示应始终位于顶部.因此,无论从何处抛出 Error,最顶层的 viewController 都应该显示 AlertMessage(例如,当异步后台进程失败时,我想要一条错误消息,无论前台显示什么 View).

I want to implement a separate ErrorHandler class, which displays error messages on certain events. The behavior of this class should be called from different other classes. When an error occurs, it will have an UIAlertView as output. The display of this AlertView should ALWAYS be on top. So no matter from where the Error gets thrown, the topmost viewController should display the AlertMessage (e.g. when an asynchronous background process fails, I want an error message, no matter what View is displayed in the foreground).

我发现了几个似乎可以解决我的问题的要点(请参阅下面的代码).但是调用 UIApplication.sharedApplication().keyWindow?.visibleViewController() 确实返回一个 nil 值.

I have found several gists which seem to solve my problem (see the code below). But calling UIApplication.sharedApplication().keyWindow?.visibleViewController() does return a nil-value.

从要点扩展

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;
  }
}
}
}

推荐答案

Amit89 提出了解决方案.您必须调用 AppDelegate 的 .window 属性.因此,我更改了以下链接中的 Swift 代码,使其按预期工作以找到最顶层的 ViewController.确保视图已经在视图层次结构中.所以这个方法不能从 .viewDidLoad

Amit89 brought a way to a solution up. You have to call the .windowproperty of the AppDelegate. So I changed the Swift code from the link below to work as intended to find the topmost ViewController. Make sure, that the view is already in the view hierarchy. So this method cannot be called from a .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评论到一个objectiveC等价物.我只更改了一些代码以使其在没有 .keyWindow 属性的情况下工作

This code originated from GitHub user Yonat in a comment to an objectiveC equivalent. I only changed the bits of code to get it to work without the .keyWindow property

这篇关于获取 iOS Swift 中的顶级 ViewController的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆