Obtenga el controller de vista actual desde el delegado de la aplicación

Soy nuevo en ios. Necesito saber el controller de vista actual desde el delegado de la aplicación … no tengo idea sobre esto y no sé para implementar esto. Estoy usando este código toimplemnt esto, pero devuelve valores nulos. Seguí este enlace: Obtener el controller de vista actual desde el delegado de la aplicación (modal es posible) necesita ayuda.

Esto es lo que utilizo para encontrar el controller de vista actual con el que el usuario probablemente interactúe:

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 shanetworkingApplication].keyWindow.rootViewController; return [UIViewController findBestViewController:viewController]; } @end 

Luego, siempre que necesite el controller de vista actual desde cualquier lugar de la aplicación, simplemente use:

 [UIViewController currentViewController] 

Aquí hay algunas funciones de class / estáticas rápidas que mantengo en una class de utilidad y puedo ayudarlo:

 // 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.shanetworkingApplication().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.shanetworkingApplication().keyWindow?.rootViewController { return navigationController as? UINavigationController } return nil } 
 UIViewController* actualVC = [anyViewController.navigationController.viewControllers lastObject]; 

Esto me ayudó a encontrar el controller de vista visible. Busqué los methods existentes y no los encontré. Entonces escribí mi propia personalizada.

 -(id)getCurrentViewController { id WindowRootVC = [[[[UIApplication shanetworkingApplication] 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; } } 

Y uso de muestra:

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

Depende de cómo configure su UI. Posiblemente pueda get su rootViewController y moverse por la jerarquía si está configurado de tal manera.

 UIViewController *vc = self.window.rootViewController; 

Recibo el controller de raíz y luego iteré a través de los VC presentados:

  UIViewController *current = [UIApplication shanetworkingApplication].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]; 

Versión rápida de la gran respuesta de jjv360, (me deshice de algunos retornos networkingundantes, y creo que Swift es más legible)

 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 } 

Desde su AppDelegate,

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

| * | Obtenga el controller de vista visible desde el controller de vista de navigation

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

| * | Presentación desde el controller de vista visible

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

estoy usando este código

 //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 

// en todos los ViewController que desea detectar

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

Esta es la mejor solución que he probado todavía.

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

Encontré esto y funciona muy bien para todos los types de segues y controlleres de vista. Es muy simple y corto, lo cual es lindo.

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

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