我遇到了一些情况,现在,它将是方便的,能够找到“最顶层”的视图控制器(一个负责当前视图),但还没有找到一种方法。
基本上,挑战是这样的:给定一个在一个类中执行,这个类不是一个视图控制器(或一个视图)[并且没有活动视图的地址],并且没有传递最顶层视图控制器的地址(或者,比如说,导航控制器的地址),是否有可能找到那个视图控制器?(如果是的话,是怎么做到的?)
或者,如果找不到,有没有可能找到最高处的风景?
我遇到了一些情况,现在,它将是方便的,能够找到“最顶层”的视图控制器(一个负责当前视图),但还没有找到一种方法。
基本上,挑战是这样的:给定一个在一个类中执行,这个类不是一个视图控制器(或一个视图)[并且没有活动视图的地址],并且没有传递最顶层视图控制器的地址(或者,比如说,导航控制器的地址),是否有可能找到那个视图控制器?(如果是的话,是怎么做到的?)
或者,如果找不到,有没有可能找到最高处的风景?
当前回答
我认为你需要一个公认的答案和@fishstix的组合
+ (UIViewController*) topMostController
{
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
return topController;
}
Swift 3.0 +
func topMostController() -> UIViewController? {
guard let window = UIApplication.shared.keyWindow, let rootViewController = window.rootViewController else {
return nil
}
var topController = rootViewController
while let newTopController = topController.presentedViewController {
topController = newTopController
}
return topController
}
其他回答
你可以通过使用找到最顶层视图控制器
NSArray *arrViewControllers=[[self navigationController] viewControllers];
UIViewController *topMostViewController=(UIViewController *)[arrViewControllers objectAtIndex:[arrViewControllers count]-1];
@implementation UIWindow (Extensions) - (UIViewController*) topMostController { UIViewController *topController = [self rootViewController]; while (topController.presentedViewController) { topController = topController.presentedViewController; } return topController; } @end
我认为大多数答案都完全忽略了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;
}
不确定这是否会帮助你通过找到最顶层的视图控制器来实现,但我试图呈现一个新的视图控制器,但如果我的根视图控制器已经有一个模态对话框,它会被阻塞,所以我将循环到所有模态视图控制器的顶部使用以下代码:
UIViewController* parentController =[UIApplication sharedApplication].keyWindow.rootViewController;
while( parentController.presentedViewController &&
parentController != parentController.presentedViewController )
{
parentController = parentController.presentedViewController;
}
一个完整的非递归版本,照顾到不同的场景:
视图控制器正在呈现另一个视图 视图控制器是一个UINavigationController 视图控制器是一个UITabBarController
objective - c
UIViewController *topViewController = self.window.rootViewController;
while (true)
{
if (topViewController.presentedViewController) {
topViewController = topViewController.presentedViewController;
} else if ([topViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *nav = (UINavigationController *)topViewController;
topViewController = nav.topViewController;
} else if ([topViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tab = (UITabBarController *)topViewController;
topViewController = tab.selectedViewController;
} else {
break;
}
}
斯威夫特 4+
extension UIWindow {
func topViewController() -> UIViewController? {
var top = self.rootViewController
while true {
if let presented = top?.presentedViewController {
top = presented
} else if let nav = top as? UINavigationController {
top = nav.visibleViewController
} else if let tab = top as? UITabBarController {
top = tab.selectedViewController
} else {
break
}
}
return top
}
}