我遇到了一些情况,现在,它将是方便的,能够找到“最顶层”的视图控制器(一个负责当前视图),但还没有找到一种方法。
基本上,挑战是这样的:给定一个在一个类中执行,这个类不是一个视图控制器(或一个视图)[并且没有活动视图的地址],并且没有传递最顶层视图控制器的地址(或者,比如说,导航控制器的地址),是否有可能找到那个视图控制器?(如果是的话,是怎么做到的?)
或者,如果找不到,有没有可能找到最高处的风景?
我遇到了一些情况,现在,它将是方便的,能够找到“最顶层”的视图控制器(一个负责当前视图),但还没有找到一种方法。
基本上,挑战是这样的:给定一个在一个类中执行,这个类不是一个视图控制器(或一个视图)[并且没有活动视图的地址],并且没有传递最顶层视图控制器的地址(或者,比如说,导航控制器的地址),是否有可能找到那个视图控制器?(如果是的话,是怎么做到的?)
或者,如果找不到,有没有可能找到最高处的风景?
当前回答
你可以通过使用找到最顶层视图控制器
NSArray *arrViewControllers=[[self navigationController] viewControllers];
UIViewController *topMostViewController=(UIViewController *)[arrViewControllers objectAtIndex:[arrViewControllers count]-1];
其他回答
最新Swift版本: 创建一个文件,命名为UIWindowExtension.swift,并粘贴以下代码片段:
import UIKit
public extension UIWindow {
public var visibleViewController: UIViewController? {
return UIWindow.getVisibleViewControllerFrom(self.rootViewController)
}
public static func getVisibleViewControllerFrom(_ vc: UIViewController?) -> UIViewController? {
if let nc = vc as? UINavigationController {
return UIWindow.getVisibleViewControllerFrom(nc.visibleViewController)
} else if let tc = vc as? UITabBarController {
return UIWindow.getVisibleViewControllerFrom(tc.selectedViewController)
} else {
if let pvc = vc?.presentedViewController {
return UIWindow.getVisibleViewControllerFrom(pvc)
} else {
return vc
}
}
}
}
func getTopViewController() -> UIViewController? {
let appDelegate = UIApplication.shared.delegate
if let window = appDelegate!.window {
return window?.visibleViewController
}
return nil
}
可以在任何地方使用:
if let topVC = getTopViewController() {
}
- (UIViewController*)topViewController {
return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
} else if (rootViewController.presentedViewController) {
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
return rootViewController;
}
}
以下是对我有效的方法。
我发现有时候控制器在键窗口上是nil,因为键窗口是一些操作系统的东西,如警报等。
+ (UIViewController*)topMostController
{
UIWindow *topWndow = [UIApplication sharedApplication].keyWindow;
UIViewController *topController = topWndow.rootViewController;
if (topController == nil)
{
// The windows in the array are ordered from back to front by window level; thus,
// the last window in the array is on top of all other app windows.
for (UIWindow *aWndow in [[UIApplication sharedApplication].windows reverseObjectEnumerator])
{
topController = aWndow.rootViewController;
if (topController)
break;
}
}
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
return topController;
}
简单的扩展UIApplication在Swift:
注意:
它关心UITabBarController中的moreNavigationController
extension UIApplication {
class func topViewController(baseViewController: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? {
if let navigationController = baseViewController as? UINavigationController {
return topViewController(navigationController.visibleViewController)
}
if let tabBarViewController = baseViewController as? UITabBarController {
let moreNavigationController = tabBarViewController.moreNavigationController
if let topViewController = moreNavigationController.topViewController where topViewController.view.window != nil {
return topViewController(topViewController)
} else if let selectedViewController = tabBarViewController.selectedViewController {
return topViewController(selectedViewController)
}
}
if let splitViewController = baseViewController as? UISplitViewController where splitViewController.viewControllers.count == 1 {
return topViewController(splitViewController.viewControllers[0])
}
if let presentedViewController = baseViewController?.presentedViewController {
return topViewController(presentedViewController)
}
return baseViewController
}
}
简单的用法:
if let topViewController = UIApplication.topViewController() {
//do sth with top view controller
}
使用下面的扩展抓取当前可见的UIViewController。适用于Swift 4.0及更高版本
Swift 4.0及以上版本:
extension UIApplication {
class func topViewController(_ viewController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = viewController as? UINavigationController {
return topViewController(nav.visibleViewController)
}
if let tab = viewController as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(selected)
}
}
if let presented = viewController?.presentedViewController {
return topViewController(presented)
}
return viewController
}
}
如何使用?
let objViewcontroller = UIApplication.topViewController()