Cómo saber si la vista de UIViewController es visible

Tengo una aplicación de tabbar, con muchas vistas. ¿Hay alguna forma de saber si un UIViewController en particular es visible desde el UIViewController? (buscando una propiedad)

La propiedad de ventana de la vista no es nula si una vista está actualmente visible, entonces verifique la vista principal en el controlador de vista:

[EDITAR] La invocación del método de vista hace que la vista se cargue (si no está cargada), lo cual es innecesario y puede ser indeseable. Sería mejor verificar primero para ver si ya está cargado. He agregado la llamada a isViewLoaded para evitar este problema.

if (viewController.isViewLoaded && viewController.view.window) { // viewController is visible } 

O si tiene un UINavigationController que administra los controladores de vista, puede verificar su propiedad visibleViewController en su lugar.

Además, en Swift en iOS 9 (o posterior):

 if viewController.viewIfLoaded?.window != nil { // viewController is visible } 

Aquí está la solución de @ progrmr como categoría de UIViewController :

 // UIViewController+Additions.h @interface UIViewController (Additions) - (BOOL)isVisible; @end // UIViewController+Additions.m #import "UIViewController+Additions.h" @implementation UIViewController (Additions) - (BOOL)isVisible { return [self isViewLoaded] && self.view.window; } @end 

Hay un par de problemas con las soluciones anteriores. Si está utilizando, por ejemplo, un UISplitViewController , la vista maestra siempre será verdadera para

 if(viewController.isViewLoaded && viewController.view.window) { //Always true for master view in split view controller } 

En su lugar, tome este enfoque simple que parece funcionar bien en la mayoría de los casos, sino en todos:

 - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; //We are now invisible self.visible = false; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; //We are now visible self.visible = true; } 

Para aquellos de ustedes que buscan una versión Swift 2.2 de la respuesta:

 if self.isViewLoaded() && (self.view.window != nil) { // viewController is visible } 

y Swift 3 :

 if self.isViewLoaded && (self.view.window != nil) { // viewController is visible } 

Desea utilizar la UITabBarController selectedViewController UITabBarController . Todos los controladores de vista conectados a un controlador de barra de tabs tienen un tabBarController propiedades tabBarController , por lo que puede, desde cualquier código del controlador de vista:

 if([[[self tabBarController] selectedViewController] isEqual:self]){ //we're in the active controller }else{ //we are not } 

Para una presentación modal sobre pantalla completa o sobre contexto, “es visible” podría significar que está en la parte superior de la stack del controlador de vista o simplemente visible, pero cubierto por otro controlador de vista.

Para verificar si el controlador de vista “es el controlador de vista superior” es bastante diferente de “es visible”, debe verificar la stack de controlador de vista del controlador de navegación del controlador de vista.

Escribí un fragmento de código para resolver este problema:

 extension UIViewController { public var isVisible: Bool { if isViewLoaded { return view.window != nil } return false } public var isTopViewController: Bool { if self.navigationController != nil { return self.navigationController?.visibleViewController === self } else if self.tabBarController != nil { return self.tabBarController?.selectedViewController == self && self.presentedViewController == nil } else { return self.presentedViewController == nil && self.isVisible } } } 

Hice una extensión rápida basada en la respuesta de @ progrmr.

Le permite verificar fácilmente si un UIViewController está en la pantalla de esta forma:

 if someViewController.isOnScreen { // Do stuff here } 

La extensión:

 // // UIViewControllerExtension.swift // import UIKit extension UIViewController{ var isOnScreen: Bool{ return self.isViewLoaded() && view.window != nil } } 

Para mis propósitos, en el contexto de un controlador de vista de contenedor, he encontrado que

 - (BOOL)isVisible { return (self.isViewLoaded && self.view.window && self.parentViewController != nil); } 

funciona bien.

si está utilizando un UINavigationController y también desea manejar vistas modales, lo siguiente es lo que uso:

 #import  UIViewController* topMostController = self.navigationController.visibleViewController; if([[NSString stringWithFormat:@"%s", class_getName([topMostController class])] isEqualToString:@"NAME_OF_CONTROLLER_YOURE_CHECKING_IN"]) { //is topmost visible view controller } 

Encontré esas funciones en UIViewController.h .

 /* These four methods can be used in a view controller's appearance callbacks to determine if it is being presented, dismissed, or added or removed as a child view controller. For example, a view controller can check if it is disappearing because it was dismissed or popped by asking itself in its viewWillDisappear: method by checking the expression ([self isBeingDismissed] || [self isMovingFromParentViewController]). */ - (BOOL)isBeingPresented NS_AVAILABLE_IOS(5_0); - (BOOL)isBeingDismissed NS_AVAILABLE_IOS(5_0); - (BOOL)isMovingToParentViewController NS_AVAILABLE_IOS(5_0); - (BOOL)isMovingFromParentViewController NS_AVAILABLE_IOS(5_0); 

Tal vez las funciones anteriores pueden detectar que ViewController aparece o no.

XCode 6.4, para iOS 8.4, ARC habilitado

Obviamente hay muchas formas de hacerlo. El que me ha funcionado es el siguiente …

 @property(nonatomic, readonly, getter=isKeyWindow) BOOL keyWindow 

Esto se puede usar en cualquier controlador de vista de la siguiente manera,

 [self.view.window isKeyWindow] 

Si llamas a esta propiedad en -(void)viewDidLoad obtienes 0, entonces si llamas esto después -(void)viewDidAppear:(BOOL)animated obtienes 1.

Espero que esto ayude a alguien. ¡Gracias! Aclamaciones.

puedes verificarlo por propiedad de la window

 if(viewController.view.window){ // view visible }else{ // no visible } 

El enfoque que utilicé para un controlador de vista presentado modal fue verificar la clase del controlador presentado. Si el controlador de vista presentado fuera ViewController2 entonces ejecutaría algún código.

 UIViewController *vc = [self presentedViewController]; if ([vc isKindOfClass:[ViewController2 class]]) { NSLog(@"this is VC2"); } 

Si está usando un controlador de navegación y solo quiere saber si está en el controlador activo y superior , entonces use:

 if navigationController?.topViewController == self { // Do something } 

Esta respuesta se basa en el comentario de @mattdipasquale .

Si tiene un escenario más complicado, consulte las otras respuestas anteriores.

Necesitaba esto para verificar si el controlador de vista es el controlador visto actualmente, lo hice comprobando si hay algún controlador de vista presentado o empujado a través del navegador, lo estoy publicando en caso de que alguien necesite dicha solución:

 if presentedViewController != nil || navigationController?.topViewController != self { //Viewcontroller isn't viewed }else{ // Now your viewcontroller is being viewed } 

Como UIAlertController se deriva de UIViewController , puede usar isBeingPresented

 if (alertController.isBeingPresented) { // alert is showing }