2010-05-05 9 views
453

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

+0

relacionadas: [Obtención de la parte superior más UIViewController] (http: // stackoverflow.com/questions/4067692/getting-the-top-most-uiviewcontroller) – Senseful

Respuesta

883

de la vista window property es no-nil si una vista es actualmente visible, a fin de comprobar la vista principal en el controlador de vista:

[EDIT] invocar el método view hace que el ver para cargar (si no está cargado) que 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 usted tiene un UINavigationController la gestión de los controladores de vista, se puede comprobar su propiedad visibleViewController lugar.

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

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

El único problema con la propiedad visibleViewControllee de un UINavigationController es el caso donde su visibleViewController presenta un controlador de vista modal. En ese caso, la vista modal se convierte en visibleViewController, lo que puede ser indeseable. ¿Cómo manejarías eso? – Moshe

+12

Esto es probablemente obvio para todos, pero para mí el código tenía que ser self.isViewLoaded && self.view.window – JeffB6688

+0

Tenga en cuenta que en iOS 7, un controlador de navegación no carga un controlador de vista insertado en la memoria de inmediato. Esto es diferente de iOS 6 donde puede presionar un controlador de vista e inmediatamente ver que navController.topViewController.isViewLoaded era verdadero. – InkGolem

25

que desea utilizar selectedViewController propiedad del UITabBarController 's. Todos los controladores de vista conectados a un controlador barra de pestañas tener un conjunto tabBarController propiedad, por lo que puede, desde el interior de cualquiera de código de los controladores de vista:

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

Esto no funciona si el controlador de vista está contenido dentro de un controlador de navegación y ese controlador se agrega al controlador de la barra de pestañas. La llamada a ViewController seleccionado devolverá el controlador de navegación y no el controlador de vista actual. –

+2

@ Antonholenberg en ese caso, obtenga el controlador de vista visible así: '((UINavigationController *) self.tabBarController.selectedViewController) .visibleViewController' – ma11hew28

+0

O incluso use la propiedad 'self.tabBarController.selectedIndex' si hemos llegado hasta aquí. –

82

Aquí es @ solución de progrmr como una categoría 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 
2

se puede comprobar por window propiedad

if(viewController.view.window){ 

// view visible 

}else{ 

// no visible 

} 
3

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

#import <objc/runtime.h> 

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 
} 
+2

He encontrado esta manera de ser más confiable que la respuesta aceptada, cuando un controlador de navegación está disponible. Esto se puede acortar a: if ([self.navigationController.visibleViewController isKindOfClass: [self class]]) { – Darren

2

El enfoque que utilicé para un controlador de vista presentado modalmente 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"); 
} 
39

Hay un par de problemas con las soluciones anteriores. Si está utilizando, por ejemplo, un UISplitViewController, la vista principal siempre devolverá cierto para

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

su lugar, tomar este enfoque simple que parece funcionar bien en la mayoría, si no todos los casos:

- (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; 
} 
+1

¿Sigue siendo cierto en xCode 7.1.1? El maestro de mi UISplitViewController devuelve NO para viewController.view.window. Puedo estar haciendo algo mal, pero estoy bastante seguro de que este es el caso. – SAHM

7

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

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

funciona bien.

17

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

Para comprobar si el controlador de vista "es el controlador de vista superior" es bastante diferente de "es visible", debe verificar la pila de controlador de vista del controlador de navegación del controlador de vista.

me escribió una pieza 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 
     } 
    } 
} 
+0

¡Bonita publicación! FYI 'isViewLoaded' es una propiedad desde Swift 3.0. –

11

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

Se le permite comprobar fácilmente si un UIViewController estará en la pantalla de este modo:

if someViewController.isOnScreen { 
    // Do stuff here 
} 

La extensión:

// 
// UIViewControllerExtension.swift 
// 

import UIKit 

extension UIViewController{ 
    var isOnScreen: Bool{ 
     return self.isViewLoaded() && view.window != nil 
    } 
} 
1

me encontré con los que funcionan 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 se puede detectar o no apareció el ViewController.

3

XCode 6.4, 8.4 para iOS, ARC habilitado

Obviamente un montón de maneras de hacerlo. El que ha trabajado para mí es la siguiente ...

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

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

[self.view.window isKeyWindow] 

Si se llama a esta propiedad en -(void)viewDidLoad se obtiene 0 , luego si llama a esto después de -(void)viewDidAppear:(BOOL)animated obtiene 1.

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

33

Para aquellos de ustedes que buscan un Swift versión 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 
} 
2

Si está utilizando un controlador de navegación y sólo quieren para saber si está en el active y topmost controlador, 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.

-2

Desde UIAlertController se deriva de UIViewController sólo se puede utilizar el isBeingPresented

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