【问题标题】:Get the current view controller from the app delegate从应用委托中获取当前视图控制器
【发布时间】:2014-09-09 14:22:15
【问题描述】:

我是 ios 新手。我需要从应用程序委托中知道当前的视图控制器。我对此一无所知,也不知道如何实现它。我正在使用此代码来实现这一点,但它返回空值。 我跟着这个链接- Get current view controller from the app delegate (modal is possible) 需要帮助。

【问题讨论】:

  • 你在使用导航控制器吗?否则发布您的代码以更好地理解

标签: ios objective-c delegates appdelegate


【解决方案1】:

这是我用来查找用户最有可能与之交互的当前视图控制器的方法:

UIViewController+Utils.h

#import <UIKit/UIKit.h>

@interface UIViewController (Utils)

+(UIViewController*) currentViewController;

@end

UIViewController+Utils.m

#import "UIViewController+Utils.h"

@implementation UIViewController (Utils)

+(UIViewController*) findBestViewController:(UIViewController*)vc {

    if (vc.presentedViewController) {

        // Return presented view controller
        return [UIViewController findBestViewController:vc.presentedViewController];

    } else if ([vc isKindOfClass:[UISplitViewController class]]) {

        // Return right hand side
        UISplitViewController* svc = (UISplitViewController*) vc;
        if (svc.viewControllers.count > 0)
            return [UIViewController findBestViewController:svc.viewControllers.lastObject];
        else
            return vc;

    } else if ([vc isKindOfClass:[UINavigationController class]]) {

        // Return top view
        UINavigationController* svc = (UINavigationController*) vc;
        if (svc.viewControllers.count > 0)
            return [UIViewController findBestViewController:svc.topViewController];
        else
            return vc;

    } else if ([vc isKindOfClass:[UITabBarController class]]) {

        // Return visible view
        UITabBarController* svc = (UITabBarController*) vc;
        if (svc.viewControllers.count > 0)
            return [UIViewController findBestViewController:svc.selectedViewController];
        else
            return vc;

    } else {

        // Unknown view controller type, return last child view controller
        return vc;

    }

}

+(UIViewController*) currentViewController {

    // Find best view controller
    UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
    return [UIViewController findBestViewController:viewController];

}

@end

然后,每当我需要应用程序中任何地方的当前视图控制器时,只需使用:

[UIViewController currentViewController]

【讨论】:

    【解决方案2】:

    这里有一些 swift 中的类/静态函数,我保留在 Utility 类中,可以帮助您:

    // Returns the most recently presented UIViewController (visible)
    class func getCurrentViewController() -> UIViewController? {
    
        // If the root view is a navigation controller, we can just return the visible ViewController
        if let navigationController = getNavigationController() {
    
            return navigationController.visibleViewController
        }
    
        // Otherwise, we must get the root UIViewController and iterate through presented views
        if let rootController = UIApplication.shared.keyWindow?.rootViewController {
    
            var currentController: UIViewController! = rootController
    
            // Each ViewController keeps track of the view it has presented, so we
            // can move from the head to the tail, which will always be the current view
            while( currentController.presentedViewController != nil ) {
    
                currentController = currentController.presentedViewController
            }
            return currentController
        }
        return nil
    }
    
    // Returns the navigation controller if it exists
    class func getNavigationController() -> UINavigationController? {
    
        if let navigationController = UIApplication.shared.keyWindow?.rootViewController  {
    
            return navigationController as? UINavigationController
        }
        return nil
    }
    

    【讨论】:

    • 我通过修改成功地使用了它来编译它。需要重新安排。
    • @alaxandermiller,我怎样才能使用这些来获取视图控制器名称作为字符串?
    【解决方案3】:

    jjv360 的最佳答案的 Swift 版本, (我去掉了一些多余的返回,我觉得 Swift 的可读性更好)

    func getCurrentViewController(_ vc: UIViewController) -> UIViewController? {
        if let pvc = vc.presentedViewController {
            return getCurrentViewController(pvc)
        }
        else if let svc = vc as? UISplitViewController, svc.viewControllers.count > 0 {
            return getCurrentViewController(svc.viewControllers.last!)
        }
        else if let nc = vc as? UINavigationController, nc.viewControllers.count > 0 {
            return getCurrentViewController(nc.topViewController!)
        }
        else if let tbc = vc as? UITabBarController {
            if let svc = tbc.selectedViewController {
                return getCurrentViewController(svc)
            }
        }
        return vc
    }
    

    来自您的 AppDelegate,

        guard let rvc = self.window?.rootViewController else {
            return
        }
        if let vc = getCurrentViewController(rvc) {
            // do your stuff here
        }
    

    【讨论】:

      【解决方案4】:

      这帮助我找到了可见的视图控制器。我搜索了现有的方法,但没有找到。所以我自己写了一个。

      -(id)getCurrentViewController
      {
          id WindowRootVC = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
      
          id currentViewController = [self findTopViewController:WindowRootVC];
      
          return currentViewController;
      }
      
      -(id)findTopViewController:(id)inController
      {
          /* if ur using any Customs classes, do like this.
           * Here SlideNavigationController is a subclass of UINavigationController.
           * And ensure you check the custom classes before native controllers , if u have any in your hierarchy.
          if ([inController isKindOfClass:[SlideNavigationController class]])
          {
              return [self findTopViewController:[inController visibleViewController]];
          }
          else */
          if ([inController isKindOfClass:[UITabBarController class]])
          {
              return [self findTopViewController:[inController selectedViewController]];
          }
          else if ([inController isKindOfClass:[UINavigationController class]])
          {
              return [self findTopViewController:[inController visibleViewController]];
          }
          else if ([inController isKindOfClass:[UIViewController class]])
          {
              return inController;
          }
          else
          {
              NSLog(@"Unhandled ViewController class : %@",inController);
              return nil;
          }
      }
      

      和样品使用:

      -(void)someMethod
      {
          id currentVC = [self getCurrentViewController];
              if (currentVC)
              {
                  NSLog(@"currentVC :%@",currentVC);
              }
      }
      

      【讨论】:

        【解决方案5】:

        这取决于您如何设置用户界面。如果以这种方式设置,您可能会获取您的 rootViewController 并在层次结构中移动。

        UIViewController *vc = self.window.rootViewController;
        

        【讨论】:

        • 我以这种方式获取视图控制器名称 - 最后一个视图控制器是 vc== 但我想要视图控制器的名称。
        • 如果你关注这个并且你想要控制器的名称然后尝试 id vc = self.window.rootViewController; NSLog(@"控制器名称: %@", [vc 类]);
        【解决方案6】:
        UIViewController* actualVC = [anyViewController.navigationController.viewControllers lastObject];
        

        【讨论】:

          【解决方案7】:

          我得到根控制器,然后遍历提供的 VC:

           UIViewController *current = [UIApplication sharedApplication].keyWindow.rootViewController;
          
          while (current.presentedViewController) {
              current = current.presentedViewController;
          }
          //now you can use current, for example to present an alert view controller:
          [current presentViewController:alert animated:YES completion:nil];
          

          【讨论】:

            【解决方案8】:

            |*|从 Navigation View Controller 获取 Visible View Controller

            let NavVccVar = UIApplication.sharedApplication().keyWindow?.rootViewController as! UINavigationController
            let ShnSrnVar = NavVccVar.visibleViewController
            

            |*|从可见视图控制器呈现

            let NavVccVar = UIApplication.sharedApplication().keyWindow?.rootViewController as! UINavigationController
            NavVccVar.visibleViewController!.presentViewController(NamVccVar, animated: true, completion: nil)
            

            【讨论】:

              【解决方案9】:

              这是我尝试过的最好的解决方案

              + (UIViewController*) topMostController
              {
                  UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
              
                  while (topController.presentedViewController) {
                      topController = topController.presentedViewController;
                  }
              
                  return topController;
              }
              

              【讨论】:

                【解决方案10】:

                Swift 解决方案 对于 iOS 13+ 我们有SceneDelgate 和多个窗口,所以您需要使用以下代码:

                private func getCurrentViewController() -> UIViewController? {
                    if let rootViewController = UIApplication.shared.windows.first?.rootViewController {
                        
                        if let presentedViewController = rootViewController.presentedViewController {
                            return presentedViewController
                        }
                        
                        return rootViewController
                    }
                    
                    return nil
                } 
                

                【讨论】:

                  【解决方案11】:

                  我正在使用此代码-

                  //in AppDelegate:
                  
                  @interface AppDelegate()
                  
                  {
                  
                      id lastViewController;
                  
                  }
                  
                  
                  @implementation AppDelegate
                  
                  -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
                  (NSDictionary *)launchOptions
                  
                  {
                  
                      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleCurrentViewController) name:@"CurrentViewController" object:nil];
                  
                  
                  }
                  
                  -(void)handleCurrentViewController:(NSNotification *)notification
                   {
                  
                      if([[notification userInfo] objectForKey:@"lastViewController"])
                     {
                  
                          lastViewController = [[notification userInfo] objectForKey:@"lastViewController"];
                  
                      }
                  }
                  
                  -(void)applicationDidEnterBackground:(UIApplication *)application
                  {  
                  
                      NSLog(@"last view controller is %@", [(UIViewController *)lastViewController class]);
                  
                  }
                  
                  @end
                  

                  //在您要检测的每个 ViewController 中

                  @implementation SomeViewController
                  
                  -(void) viewWillDisappear:(BOOL)animated 
                  {
                      [super viewWillDisappear:animated];
                  
                      [[NSNotificationCenter defaultCenter] postNotificationName:@"CurrentViewController" object:nil userInfo:[NSDictionary dictionaryWithObjectsAndKeys:self, @"lastViewController", nil]];
                  
                  }
                  

                  【讨论】:

                    【解决方案12】:

                    我发现了这一点,它适用于所有类型的 segue 和视图控制器。它非常简单和简短,这很好。

                    +(UIViewController*) getTopController{ UIViewController *topViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

                    while (topViewController.presentedViewController) {
                        topViewController = topViewController.presentedViewController;
                    }
                    
                    return topViewController; }
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2013-10-26
                      • 1970-01-01
                      • 2021-05-30
                      • 2021-03-12
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-03-23
                      • 2023-03-21
                      相关资源
                      最近更新 更多