我遇到了一些情况,现在,它将是方便的,能够找到“最顶层”的视图控制器(一个负责当前视图),但还没有找到一种方法。
基本上,挑战是这样的:给定一个在一个类中执行,这个类不是一个视图控制器(或一个视图)[并且没有活动视图的地址],并且没有传递最顶层视图控制器的地址(或者,比如说,导航控制器的地址),是否有可能找到那个视图控制器?(如果是的话,是怎么做到的?)
或者,如果找不到,有没有可能找到最高处的风景?
我遇到了一些情况,现在,它将是方便的,能够找到“最顶层”的视图控制器(一个负责当前视图),但还没有找到一种方法。
基本上,挑战是这样的:给定一个在一个类中执行,这个类不是一个视图控制器(或一个视图)[并且没有活动视图的地址],并且没有传递最顶层视图控制器的地址(或者,比如说,导航控制器的地址),是否有可能找到那个视图控制器?(如果是的话,是怎么做到的?)
或者,如果找不到,有没有可能找到最高处的风景?
当前回答
这对于从任何根视图控件中找到top viewcontroller1非常有效
+ (UIViewController *)topViewControllerFor:(UIViewController *)viewController
{
if(!viewController.presentedViewController)
return viewController;
return [MF5AppDelegate topViewControllerFor:viewController.presentedViewController];
}
/* View Controller for Visible View */
AppDelegate *app = [UIApplication sharedApplication].delegate;
UIViewController *visibleViewController = [AppDelegate topViewControllerFor:app.window.rootViewController];
其他回答
我认为大多数答案都完全忽略了UINavigationViewController,所以我用下面的实现来处理这个用例。
+ (UIViewController *)topMostController {
UIViewController * topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController || [topController isMemberOfClass:[UINavigationController class]]) {
if([topController isMemberOfClass:[UINavigationController class]]) {
topController = [topController childViewControllers].lastObject;
} else {
topController = topController.presentedViewController;
}
}
return topController;
}
Swift 4.2中一个简洁而全面的解决方案,考虑了UINavigationControllers, UITabBarControllers, presenting和子视图控制器:
extension UIViewController {
func topmostViewController() -> UIViewController {
if let navigationVC = self as? UINavigationController,
let topVC = navigationVC.topViewController {
return topVC.topmostViewController()
}
if let tabBarVC = self as? UITabBarController,
let selectedVC = tabBarVC.selectedViewController {
return selectedVC.topmostViewController()
}
if let presentedVC = presentedViewController {
return presentedVC.topmostViewController()
}
if let childVC = children.last {
return childVC.topmostViewController()
}
return self
}
}
extension UIApplication {
func topmostViewController() -> UIViewController? {
return keyWindow?.rootViewController?.topmostViewController()
}
}
用法:
let viewController = UIApplication.shared.topmostViewController()
迅速:
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;
}
}
}
用法:
if let topController = window.visibleViewController() {
println(topController)
}
你应该使用:
[UIApplication sharedApplication].window.rootViewController;
当[UIApplication sharedApplication]上有一个uiactionsheet时。keyWindow,这是不正确的使用keyWindow在这个答案中提到。
另一个解决方案依赖于responder链,它可能工作,也可能不工作,这取决于第一个responder是什么:
获取第一个响应器。 获取与第一个responder相关联的UIViewController。
示例伪代码:
+ (UIViewController *)currentViewController {
UIView *firstResponder = [self firstResponder]; // from the first link above, but not guaranteed to return a UIView, so this should be handled more appropriately.
UIViewController *viewController = [firstResponder viewController]; // from the second link above
return viewController;
}