如果没有UINavigationController,我似乎无法得到最顶端的UIViewController。以下是我目前所掌握的:

UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(vc, animated: true, completion: nil)

然而,它似乎没有做任何事情。keyWindow和rootViewController似乎也不是nil值,所以可选的链接应该不是问题。

注意:这样做不是一个好主意。它打破了MVC模式。


当前回答

对于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)

其他回答

presentViewController显示一个视图控制器。它不会返回一个视图控制器。如果你不使用UINavigationController,你可能正在寻找presenttedviewcontroller,你需要从根开始,向下迭代所呈现的视图。

if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController {
    while let presentedViewController = topController.presentedViewController {
        topController = presentedViewController
    }

    // topController should now be your topmost view controller
}

对于Swift 3+:

if var topController = UIApplication.shared.keyWindow?.rootViewController {
    while let presentedViewController = topController.presentedViewController {
        topController = presentedViewController
    }

    // topController should now be your topmost view controller
}

适用于iOS 13+

let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first

if var topController = keyWindow?.rootViewController {
    while let presentedViewController = topController.presentedViewController {
        topController = presentedViewController
    }

// topController should now be your topmost view controller
}

使用这段代码找到top most UIViewController

func getTopViewController() -> UIViewController? {
    var topController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController
    while topController?.presentedViewController != nil {
        topController = topController?.presentedViewController
    }
    return topController
}
  var topViewController: UIViewController? {
        guard var topViewController = UIApplication.shared.keyWindow?.rootViewController else { return nil }
        while let presentedViewController = topViewController.presentedViewController {
            topViewController = presentedViewController
        }
        return topViewController
    }

试试这个

let topVisibleVC = UIApplication.shared.keyWindow?.rootViewController?.visibleViewController
    extension UIApplication {
        
       public var mainKeyWindow: UIWindow? {
           if #available(iOS 13, *) {
             return UIApplication.shared.connectedScenes
            .filter { $0.activationState == .foregroundActive }
            .first(where: { $0 is UIWindowScene })
            .flatMap { $0 as? UIWindowScene }?.windows
            .first(where: \.isKeyWindow)
           } else {
              return UIApplication.shared.windows.first { $0.isKeyWindow }
           }
        }
    

    public var rootViewController: UIViewController? {
        guard let keyWindow = UIApplication.shared.mainKeyWindow, let rootViewController = keyWindow.rootViewController else {
            return nil
        }
        return rootViewController
    }

    public func topViewController(controller: UIViewController? = UIApplication.shared.rootViewController) -> UIViewController? {

        if controller == nil {
            return topViewController(controller: rootViewController)
        }
        
        if let navigationController = controller as? UINavigationController {
            return topViewController(controller: navigationController.visibleViewController)
        }

        if let tabController = controller as? UITabBarController {
            if let selectedViewController = tabController.selectedViewController {
                return topViewController(controller: selectedViewController)
            }
        }

        if let presentedViewController = controller?.presentedViewController {
            return topViewController(controller: presentedViewController)
        }

        return controller
    }
}

Swift 5.2及以上版本