我遇到了一些情况,现在,它将是方便的,能够找到“最顶层”的视图控制器(一个负责当前视图),但还没有找到一种方法。
基本上,挑战是这样的:给定一个在一个类中执行,这个类不是一个视图控制器(或一个视图)[并且没有活动视图的地址],并且没有传递最顶层视图控制器的地址(或者,比如说,导航控制器的地址),是否有可能找到那个视图控制器?(如果是的话,是怎么做到的?)
或者,如果找不到,有没有可能找到最高处的风景?
我遇到了一些情况,现在,它将是方便的,能够找到“最顶层”的视图控制器(一个负责当前视图),但还没有找到一种方法。
基本上,挑战是这样的:给定一个在一个类中执行,这个类不是一个视图控制器(或一个视图)[并且没有活动视图的地址],并且没有传递最顶层视图控制器的地址(或者,比如说,导航控制器的地址),是否有可能找到那个视图控制器?(如果是的话,是怎么做到的?)
或者,如果找不到,有没有可能找到最高处的风景?
当前回答
你可以通过使用找到最顶层视图控制器
NSArray *arrViewControllers=[[self navigationController] viewControllers];
UIViewController *topMostViewController=(UIViewController *)[arrViewControllers objectAtIndex:[arrViewControllers count]-1];
其他回答
我认为大多数答案都完全忽略了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;
}
一个完整的非递归版本,照顾到不同的场景:
视图控制器正在呈现另一个视图 视图控制器是一个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
}
}
不确定这是否会帮助你通过找到最顶层的视图控制器来实现,但我试图呈现一个新的视图控制器,但如果我的根视图控制器已经有一个模态对话框,它会被阻塞,所以我将循环到所有模态视图控制器的顶部使用以下代码:
UIViewController* parentController =[UIApplication sharedApplication].keyWindow.rootViewController;
while( parentController.presentedViewController &&
parentController != parentController.presentedViewController )
{
parentController = parentController.presentedViewController;
}
之前的答案似乎不能处理rootController是UITabBarController或UINavigationController的情况。
下面是swift中适用于这些情况的函数:
func getCurrentView() -> UIViewController?
{
if let window = UIApplication.sharedApplication().keyWindow, var currentView: UIViewController = window.rootViewController
{
while (currentView.presentedViewController != nil)
{
if let presented = currentView.presentedViewController
{
currentView = presented
}
}
if currentView is UITabBarController
{
if let visible = (currentView as! UITabBarController).selectedViewController
{
currentView = visible;
}
}
if currentView is UINavigationController
{
if let visible = (currentView as! UINavigationController).visibleViewController
{
currentView = visible;
}
}
return currentView
}
return nil
}
我最近在我的一个项目中遇到了这种情况,当网络状态发生变化时,需要显示一个通知视图,无论显示的控制器是什么,无论类型是什么(UINavigationController,经典控制器或自定义视图控制器)。
所以我刚刚发布了我的代码,这很简单,实际上是基于一个协议,所以它对每种类型的容器控制器都是灵活的。 它似乎与上一个答案有关,但方式更加灵活。
你可以从这里获取代码:PPTopMostController
并得到最顶级的控制器使用
UIViewController *c = [UIViewController topMostController];