Tengo una aplicación de barra de pestañas, con muchas vistas. ¿Hay alguna manera de saber si un particular UIViewController
es visible actualmente desde dentro UIViewController
? (buscando una propiedad)
Tengo una aplicación de barra de pestañas, con muchas vistas. ¿Hay alguna manera de saber si un particular UIViewController
es visible actualmente desde dentro UIViewController
? (buscando una propiedad)
Respuestas:
La propiedad de ventana de la vista no es nula si una vista está actualmente visible, así que verifique la vista principal en el controlador de vista:
Invocar el 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. Agregué la llamada a isViewLoaded para evitar este problema.
if (viewController.isViewLoaded && viewController.view.window) {
// viewController is visible
}
Desde iOS9 se ha vuelto más fácil:
if viewController.viewIfLoaded?.window != nil {
// viewController is visible
}
O si tiene un UINavigationController que administra los controladores de vista, puede verificar su propiedad visibleViewController en su lugar.
topViewController
.
Aquí está la solución de @progrmr como UIViewController
categoría:
// 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, a UISplitViewController
, la vista maestra siempre devolverá verdadero para
if(viewController.isViewLoaded && viewController.view.window) {
//Always true for master view in split view controller
}
En cambio, tome este enfoque simple que parece funcionar bien en la mayoría, si no en 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;
}
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
}
Para presentaciones modales en pantalla completa o en 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 verificar si el controlador de vista "es el controlador de vista superior" es bastante diferente de "es visible", debe verificar la pila del controlador de vista del controlador de navegación del controlador de vista.
Escribí un 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
}
}
}
isViewLoaded
es una propiedad desde Swift 3.0.
Desea usar la propiedad de UITabBarController
's selectedViewController
. Todos los controladores de vista conectados a un controlador de barra de pestañas tienen un tabBarController
conjunto de propiedades, por lo que puede, desde cualquiera de los códigos de los controladores de vista:
if([[[self tabBarController] selectedViewController] isEqual:self]){
//we're in the active controller
}else{
//we are not
}
((UINavigationController *)self.tabBarController.selectedViewController).visibleViewController
Hice una extensión rápida basada en la respuesta de @progrmr.
Le permite verificar fácilmente si hay un UIViewController
en la pantalla de esta manera:
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 <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
}
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");
}
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 si ViewController
aparece o no.
XCode 6.4, para iOS 8.4, ARC habilitado
Obviamente 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 llama a esta propiedad -(void)viewDidLoad
obtiene 0, entonces si llama a esto después de -(void)viewDidAppear:(BOOL)animated
obtener 1.
Espero que esto ayude a alguien. ¡Gracias! Salud.
Si está utilizando un controlador de navegación y solo quiere saber si está en el controlador activo y superior , utilice:
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.
puedes consultarlo por window
propiedad
if(viewController.view.window){
// view visible
}else{
// no visible
}
Necesitaba esto para verificar si el controlador de vista es el controlador de vista actual, 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 tal solución:
if presentedViewController != nil || navigationController?.topViewController != self {
//Viewcontroller isn't viewed
}else{
// Now your viewcontroller is being viewed
}
Utilizo esta pequeña extensión en Swift 5 , lo que hace que sea simple y fácil verificar cualquier objeto que sea miembro de UIView .
extension UIView {
var isVisible: Bool {
guard let _ = self.window else {
return false
}
return true
}
}
Entonces, solo lo uso como una simple comprobación de declaración if ...
if myView.isVisible {
// do something
}
¡Espero que ayude! :)