获得 iOS Swift 中的前 ViewController
Get the top ViewController in iOS Swift
我想实现一个单独的 ErrorHandler class,它显示特定事件的错误消息。此 class 的行为应该从不同的其他 class 中调用。
当发生错误时,它将有一个 UIAlertView
作为输出。
此 AlertView 的显示应始终位于顶部。所以无论从哪里抛出错误,最上面的 viewController 都应该显示 AlertMessage (例如,当异步后台进程失败时,我想要一条错误消息,无论前台显示什么视图)。
我发现了几个似乎可以解决我的问题的要点(见下面的代码)。
但是调用 UIApplication.sharedApplication().keyWindow?.visibleViewController()
确实 return 一个零值。
要点的扩展
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;
}
}
}
}
您是否从同一个 link 尝试过此操作?
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
}
}
Amit89 提出了解决方法。您必须调用 AppDelegate 的 .window
属性。
因此,我将下面 link 中的 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 in a comment 到 objectiveC 等价物。我只更改了代码位以使其在没有 .keyWindow
属性
的情况下工作
我想实现一个单独的 ErrorHandler class,它显示特定事件的错误消息。此 class 的行为应该从不同的其他 class 中调用。
当发生错误时,它将有一个 UIAlertView
作为输出。
此 AlertView 的显示应始终位于顶部。所以无论从哪里抛出错误,最上面的 viewController 都应该显示 AlertMessage (例如,当异步后台进程失败时,我想要一条错误消息,无论前台显示什么视图)。
我发现了几个似乎可以解决我的问题的要点(见下面的代码)。
但是调用 UIApplication.sharedApplication().keyWindow?.visibleViewController()
确实 return 一个零值。
要点的扩展
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;
}
}
}
}
您是否从同一个 link 尝试过此操作?
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
}
}
Amit89 提出了解决方法。您必须调用 AppDelegate 的 .window
属性。
因此,我将下面 link 中的 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 in a comment 到 objectiveC 等价物。我只更改了代码位以使其在没有 .keyWindow
属性