有没有一种方式从AppDelegate获取当前视图控制器?我知道有rootViewController,但这不是我想要的。
如果您的应用程序的根视图控制器是一个 UINavigationController
,您可以这样做:
((UINavigationController*)appDelegate.window.rootViewController).visibleViewController;
同样地,如果这是一个UITabBarController
,您可以这样做:
((UITabBarController*)appDelegate.window.rootViewController).selectedViewController;
当然,像这样显式转换是不好的。更好的方法是使用强类型自己捕获引用。
这可能会有所帮助
- (UIViewController *)topViewController{
return [self topViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController *)topViewController:(UIViewController *)rootViewController
{
if (rootViewController.presentedViewController == nil) {
return rootViewController;
}
if ([rootViewController.presentedViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
UIViewController *lastViewController = [[navigationController viewControllers] lastObject];
return [self topViewController:lastViewController];
}
UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;
return [self topViewController:presentedViewController];
}
Swift版本:
extension UIApplication {
class func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
return base
}
}
制作扩展:
extension UIApplication {
class func topViewController(base: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(nav.visibleViewController)
}
if let tab = base as? UITabBarController {
let moreNavigationController = tab.moreNavigationController
if let top = moreNavigationController.topViewController where top.view.window != nil {
return topViewController(top)
} else if let selected = tab.selectedViewController {
return topViewController(selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(presented)
}
return base
}
}
使用方法:
if let rootViewController = UIApplication.topViewController() {
//do sth with root view controller
}
获取appDelegate对象:
MyAppDelegate *tmpDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
正如beryllium建议的那样,您可以使用UINavigationController的属性来访问当前的视图控制器。
因此,代码将如下所示:
id myCurrentController = tmpDelegate.myNavigationController.topViewController;
或者:NSArray *myCurrentViewControllers = tmpDelegate.myNavigationController.viewControllers;
UIViewController *parentViewController = [[[UIApplication sharedApplication] delegate] window].rootViewController;
while (parentViewController.presentedViewController != nil){
parentViewController = parentViewController.presentedViewController;
}
UIViewController *currentViewController = parentViewController;
对于那些不使用UINavigationController
而是使用默认视图控制器UIViewController
的人,您可以在AppDelegate
中使用以下代码检查哪个视图控制器处于活动状态(或已呈现):
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
if let rootViewController = self.window!.rootViewController {
if let presentedViewController = rootViewController.presentedViewController {
return presentedViewController.supportedInterfaceOrientations()
}
} // Else current view controller is DefaultViewController
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
正如您所看到的,我正在检查当前视图控制器,以支持特定视图控制器的不同界面方向。对于其他有兴趣使用此方法来支持特定方向的人,应在需要特定方向的每个视图控制器中放置以下内容。
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.All.rawValue)
}
注意: 这段代码使用的是Swift 1.2
if let
改为 while let
,这样它就能够获取最顶部的值。 - mginn基于 A.G 的方案,使用 Swift 4+ 语法的 UIApplication 扩展。
public extension UIApplication {
class func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
let moreNavigationController = tab.moreNavigationController
if let top = moreNavigationController.topViewController, top.view.window != nil {
return topViewController(base: top)
} else if let selected = tab.selectedViewController {
return topViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
return base
}
}
用法示例:
if let rootViewController = UIApplication.topViewController() {
//do something with rootViewController
}
快速解决方案:
self.window.rootViewController.presentedViewController.
经常需要检索当前显示的视图控制器。这可能意味着当前UINavigationController堆栈顶部的视图控制器,当前呈现的视图控制器等等。因此,我编写了这个函数,它大多数情况下可以找到它,并且您可以在UIViewController扩展中使用它。
Swift 3代码:
func currentViewController(
_ viewController: UIViewController? =
UIApplication.shared.keyWindow?.rootViewController)
-> UIViewController? {
guard let viewController =
viewController else { return nil }
if let viewController =
viewController as? UINavigationController {
if let viewController =
viewController.visibleViewController {
return currentViewController(viewController)
} else {
return currentViewController(
viewController.topViewController)
}
} else if let viewController =
viewController as? UITabBarController {
if let viewControllers =
viewController.viewControllers,
viewControllers.count > 5,
viewController.selectedIndex >= 4 {
return currentViewController(
viewController.moreNavigationController)
} else {
return currentViewController(
viewController.selectedViewController)
}
} else if let viewController =
viewController.presentedViewController {
return viewController
} else if viewController.childViewControllers.count > 0 {
return viewController.childViewControllers[0]
} else {
return viewController
}
}
调用方法:currentViewController()