【问题标题】:Get the top ViewController in iOS Swift获取 iOS Swift 中的顶级 ViewController
【发布时间】:2015-08-14 18:09:59
【问题描述】:

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

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

gist 的扩展

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

【问题讨论】:

  • 在您可能的情况下,您可以在 githHub 或其他地方分享您的 ErrorHandler 类吗?

标签: swift uialertview viewcontroller uiwindow


【解决方案1】:

Amit89 提供了一种解决方案。您必须调用 AppDelegate 的 .windowproperty。 因此,我更改了下面链接中的 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 中的 comment 到 ObjectiveC 等效项。我只更改了一些代码以使其在没有.keyWindow 属性的情况下工作

【讨论】:

  • 我正在使用你的扩展来查找最顶层的 ViewController,但是如果出现警报,上面的代码会给出 UIAlertController。如何在 UIAlertController 下获取顶视图控制器?
【解决方案2】:

您是否从同一个链接尝试过这个?

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

【讨论】:

  • 是的,我做到了:致命错误:在展开可选值时意外发现 nil 问题是,'UIApplication.sharedApplication().keyWindow?.rootViewController)' 返回 nil
  • 使用应用委托类的window属性代替key window。
  • 如果有帮助,应该被接受为正确答案。
猜你喜欢
  • 2017-05-14
  • 2018-12-30
  • 1970-01-01
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多