如果没有UINavigationController,我似乎无法得到最顶端的UIViewController。以下是我目前所掌握的:
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(vc, animated: true, completion: nil)
然而,它似乎没有做任何事情。keyWindow和rootViewController似乎也不是nil值,所以可选的链接应该不是问题。
注意:这样做不是一个好主意。它打破了MVC模式。
对我来说,最好的解决方案是一个带有函数的扩展。
用这个扩展名创建一个swift文件
首先是UIWindow扩展:
public extension UIWindow {
var visibleViewController: UIViewController? {
return UIWindow.visibleVC(vc: self.rootViewController)
}
static func visibleVC(vc: UIViewController?) -> UIViewController? {
if let navigationViewController = vc as? UINavigationController {
return UIWindow.visibleVC(vc: navigationViewController.visibleViewController)
} else if let tabBarVC = vc as? UITabBarController {
return UIWindow.visibleVC(vc: tabBarVC.selectedViewController)
} else {
if let presentedVC = vc?.presentedViewController {
return UIWindow.visibleVC(vc: presentedVC)
} else {
return vc
}
}
}
}
在该文件中添加函数
func visibleViewController() -> UIViewController? {
let appDelegate = UIApplication.shared.delegate
if let window = appDelegate!.window {
return window?.visibleViewController
}
return nil
}
如果你想使用它,你可以在任何地方调用它。
例子:
override func viewDidLoad() {
super.viewDidLoad()
if let topVC = visibleViewController() {
//show some label or text field
}
}
文件代码如下:
import UIKit
public extension UIWindow {
var visibleViewController: UIViewController? {
return UIWindow.visibleVC(vc: self.rootViewController)
}
static func visibleVC(vc: UIViewController?) -> UIViewController? {
if let navigationViewController = vc as? UINavigationController {
return UIWindow.visibleVC(vc: navigationViewController.visibleViewController)
} else if let tabBarVC = vc as? UITabBarController {
return UIWindow.visibleVC(vc: tabBarVC.selectedViewController)
} else {
if let presentedVC = vc?.presentedViewController {
return UIWindow.visibleVC(vc: presentedVC)
} else {
return vc
}
}
}
}
func visibleViewController() -> UIViewController? {
let appDelegate = UIApplication.shared.delegate
if let window = appDelegate!.window {
return window?.visibleViewController
}
return nil
}
对于swift 4 / 5 +获取topmost viewController
// MARK: UIApplication extensions
extension UIApplication {
class func getTopViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return getTopViewController(base: nav.visibleViewController)
} else if let tab = base as? UITabBarController, let selected = tab.selectedViewController {
return getTopViewController(base: selected)
} else if let presented = base?.presentedViewController {
return getTopViewController(base: presented)
}
return base
}
}
如何使用
if let topVC = UIApplication.getTopViewController() {
topVC.view.addSubview(forgotPwdView)
}
对于Swift 5+,
iOS 13 +
extension UIViewController {
static func topMostViewController() -> UIViewController? {
if #available(iOS 13.0, *) {
let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
return keyWindow?.rootViewController?.topMostViewController()
}
return UIApplication.shared.keyWindow?.rootViewController?.topMostViewController()
}
func topMostViewController() -> UIViewController? {
if let navigationController = self as? UINavigationController {
return navigationController.topViewController?.topMostViewController()
}
else if let tabBarController = self as? UITabBarController {
if let selectedViewController = tabBarController.selectedViewController {
return selectedViewController.topMostViewController()
}
return tabBarController.topMostViewController()
}
else if let presentedViewController = self.presentedViewController {
return presentedViewController.topMostViewController()
}
else {
return self
}
}
}
用法:
当你在没有UIViewController实例的情况下获取topMostViewController时
guard let viewController = UIViewController.topMostViewController() else { return }
print(viewController)
当你获取UIViewController实例的topMostViewController时
let yourVC = UIViewController()
guard let vc = yourVC.topMostViewController() else { return }
print(vc)