【问题标题】:Current view controller from AppDelegate?AppDelegate 的当前视图控制器?
【发布时间】:2012-02-19 01:06:42
【问题描述】:

有没有办法从 AppDelegate 获取当前视图控制器?我知道有 rootViewController,但这不是我要找的。​​p>

【问题讨论】:

    标签: objective-c ios uiviewcontroller


    【解决方案1】:

    如果您的应用的根视图控制器是UINavigationController,您可以这样做:

    ((UINavigationController*)appDelegate.window.rootViewController).visibleViewController;
    

    同样,如果是UITabBarController,您可以这样做:

    ((UITabBarController*)appDelegate.window.rootViewController).selectedViewController;
    

    当然,像这样的显式转换是肮脏的。最好使用强类型自己捕获引用。

    【讨论】:

      【解决方案2】:

      这可能会有所帮助

      - (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
          }
      }
      

      取自: https://gist.github.com/snikch/3661188

      【讨论】:

        【解决方案3】:

        如果你有 UINavigationController 进入 appDelegate 然后使用它的属性 topViewController 或 visibleViewController

        【讨论】:

          【解决方案4】:

          做一个扩展:

          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
          }
          

          【讨论】:

          • 这个答案解决了 Apple 的 Advanced NSOperations 示例类的一个恼人问题。如果发生错误,最顶层的视图控制器是唯一可以显示警报的控制器。我可能已经让它迭代而不是递归,因为我是老式的,但这比盲目使用 UIApplication.sharedApplication().keyWindow?.rootViewController 要好得多
          【解决方案5】:

          获取 appDelegate 对象:

          MyAppDelegate *tmpDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
          

          正如铍建议的那样,您可以使用 UINavigationController 的属性来访问您当前的视图控制器。

          所以代码看起来像:

          id myCurrentController = tmpDelegate.myNavigationController.topViewController;
          

          或:

          NSArray *myCurrentViewControllers = tmpDelegate.myNavigationController.viewControllers;
          

          【讨论】:

            【解决方案6】:

            你可以从rootViewController中通过寻找它的presentedViewController来获取当前的视图控制器,像这样:

            UIViewController *parentViewController = [[[UIApplication sharedApplication] delegate] window].rootViewController;
            
            while (parentViewController.presentedViewController != nil){
                parentViewController = parentViewController.presentedViewController;
            }
            UIViewController *currentViewController = parentViewController;
            

            它适用于我。希望对你有帮助:)

            【讨论】:

              【解决方案7】:

              对于任何不使用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,使其位于最顶层。
              【解决方案8】:

              基于A.G's solution的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
              }
              

              【讨论】:

              • 太棒了!它也适用于 Tabbar,因为我只搜索 Tabbar
              【解决方案9】:

              Swift 解决方案:

               self.window.rootViewController.presentedViewController. 
              

              这应该可以满足您的需求。

              【讨论】:

              • 这种方法仅在 self 是 UIView 或类似的情况下有效,如果它是抽象类则无效。
              【解决方案10】:

              我经常需要检索当前显示的视图控制器。它可能意味着当前 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()

              【讨论】:

                【解决方案11】:

                如果有人想要使用 Objective C。

                GlobalManager.h

                //
                //  GlobalManager.h
                //  Communicator
                //
                //  Created by Mushrankhan Pathan on 21/10/21.
                //  Copyright © 2021 Ribbideo. All rights reserved.
                //
                
                #import <Foundation/Foundation.h>
                #import <UIKit/UIKit.h>
                
                NS_ASSUME_NONNULL_BEGIN
                
                @interface GlobalManager : NSObject
                
                typedef void (^ ActionBlock)(void);
                
                +(UIViewController*)currentController;
                +(UIViewController*)currentController:(UIViewController*) baseController;
                
                @end
                
                NS_ASSUME_NONNULL_END
                

                GlobalManager.m

                //
                //  GlobalManager.m
                //  Communicator
                //
                //  Created by Mushrankhan Pathan on 21/10/21.
                //  Copyright © 2021 Ribbideo. All rights reserved.
                //
                
                #import "GlobalManager.h"
                
                @implementation GlobalManager
                
                +(UIViewController*)currentController
                {
                    UIViewController *base = UIApplication.sharedApplication.keyWindow.rootViewController;
                    return [GlobalManager currentController:base];
                }
                
                +(UIViewController*)currentController:(UIViewController*) baseController
                {
                    if ([baseController isKindOfClass:[UINavigationController class]]) {
                        return [GlobalManager currentController:((UINavigationController*)baseController).visibleViewController];
                    }
                    
                    if ([baseController isKindOfClass:[UITabBarController class]]) {
                        UINavigationController* moreNavigationController = ((UITabBarController*)baseController).moreNavigationController;
                        UIViewController* top = moreNavigationController.topViewController;
                        if (top.view.window != nil) {
                            return [GlobalManager currentController:top];
                        }
                        UIViewController* selectedViewController = ((UITabBarController*)baseController).selectedViewController;
                        if (selectedViewController != nil) {
                            return [GlobalManager currentController:selectedViewController];
                        }
                    }
                    
                    if (baseController.presentedViewController != nil) {
                        return [GlobalManager currentController:baseController.presentedViewController];
                    }
                    
                    return baseController;
                }
                
                @end
                

                如何使用。

                UIViewController *currentVC = [GlobalManager currentController];
                

                【讨论】:

                  猜你喜欢
                  • 2015-02-27
                  • 2017-10-25
                  • 2021-11-12
                  • 1970-01-01
                  • 2017-04-11
                  • 2015-05-23
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多