Eu tenho um aplicativo de barra de guias, com muitas visualizações. Existe uma maneira de saber se um determinado UIViewController
item está visível no momento UIViewController
? (à procura de um imóvel)
Eu tenho um aplicativo de barra de guias, com muitas visualizações. Existe uma maneira de saber se um determinado UIViewController
item está visível no momento UIViewController
? (à procura de um imóvel)
Respostas:
A propriedade window da view é nula se uma view estiver visível no momento; portanto, verifique a view principal no controlador de view:
A chamada do método de exibição faz com que a exibição seja carregada (se não estiver carregada), o que é desnecessário e pode ser indesejável. Seria melhor verificar primeiro para ver se ele já está carregado. Eu adicionei a chamada ao isViewLoaded para evitar esse problema.
if (viewController.isViewLoaded && viewController.view.window) {
// viewController is visible
}
Desde o iOS9, ficou mais fácil:
if viewController.viewIfLoaded?.window != nil {
// viewController is visible
}
Ou, se você tiver um UINavigationController gerenciando os controladores de exibição, poderá verificar sua propriedade visibleViewController .
topViewController
.
Aqui está a solução do @ progrmr como uma UIViewController
categoria:
// 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
Existem alguns problemas com as soluções acima. Se você estiver usando, por exemplo, a UISplitViewController
, a visualização principal sempre retornará verdadeira para
if(viewController.isViewLoaded && viewController.view.window) {
//Always true for master view in split view controller
}
Em vez disso, adote esta abordagem simples que parece funcionar bem na maioria, se não em todos os 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 aqueles que procuram uma versão Swift 2.2 da resposta:
if self.isViewLoaded() && (self.view.window != nil) {
// viewController is visible
}
e Swift 3 :
if self.isViewLoaded && (self.view.window != nil) {
// viewController is visible
}
Para apresentações modais em tela cheia ou em contexto, "é visível" pode significar que está no topo da pilha do controlador de exibição ou apenas visível, mas coberto por outro controlador de exibição.
Para verificar se o controlador de visualização "é o controlador de visualização superior" é bastante diferente de "está visível", verifique a pilha do controlador de visualização do controlador de navegação do controlador de visualização.
Eu escrevi um pedaço de código para resolver esse 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
é uma propriedade desde o Swift 3.0.
Você quer usar o UITabBarController
's selectedViewController
propriedade. Todos os controladores de visualização conectados a um controlador de barra de guias têm um tabBarController
conjunto de propriedades, para que você possa, de qualquer código do controlador de visualização:
if([[[self tabBarController] selectedViewController] isEqual:self]){
//we're in the active controller
}else{
//we are not
}
((UINavigationController *)self.tabBarController.selectedViewController).visibleViewController
Fiz uma extensão rápida com base na resposta do @ progrmr.
Ele permite que você verifique facilmente se a UIViewController
está na tela assim:
if someViewController.isOnScreen {
// Do stuff here
}
A extensão:
//
// UIViewControllerExtension.swift
//
import UIKit
extension UIViewController{
var isOnScreen: Bool{
return self.isViewLoaded() && view.window != nil
}
}
Para meus propósitos, no contexto de um controlador de exibição de contêiner, descobri que
- (BOOL)isVisible {
return (self.isViewLoaded && self.view.window && self.parentViewController != nil);
}
funciona bem.
se você estiver utilizando um UINavigationController e também quiser lidar com modos de exibição modais, é o que eu 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
}
A abordagem que usei para um controlador de exibição apresentado modal foi verificar a classe do controlador apresentado. Se o controlador de exibição apresentado fosse ViewController2
, eu executaria algum código.
UIViewController *vc = [self presentedViewController];
if ([vc isKindOfClass:[ViewController2 class]]) {
NSLog(@"this is VC2");
}
Eu encontrei essas funções em 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);
Talvez as funções acima possam detectar a ViewController
aparência ou não.
XCode 6.4, para iOS 8.4, habilitado para ARC
Obviamente, muitas maneiras de fazê-lo. O que funcionou para mim é o seguinte ...
@property(nonatomic, readonly, getter=isKeyWindow) BOOL keyWindow
Isso pode ser usado em qualquer controlador de exibição da seguinte maneira,
[self.view.window isKeyWindow]
Se você chamar essa propriedade, -(void)viewDidLoad
obtém 0, e depois -(void)viewDidAppear:(BOOL)animated
chamar 1.
Espero que isso ajude alguém. Obrigado! Felicidades.
Se você estiver usando um controlador de navegação e apenas quiser saber se está no controlador ativo e superior , use:
if navigationController?.topViewController == self {
// Do something
}
Esta resposta é baseada no comentário de @mattdipasquale .
Se você tiver um cenário mais complicado, consulte as outras respostas acima.
você pode verificá-lo por window
propriedade
if(viewController.view.window){
// view visible
}else{
// no visible
}
Eu precisava disso para verificar se o controlador de exibição é o atual controlador visualizado, fiz isso verificando se há algum controlador de exibição apresentado ou enviado pelo navegador, estou publicando-o no caso de alguém precisar dessa solução:
if presentedViewController != nil || navigationController?.topViewController != self {
//Viewcontroller isn't viewed
}else{
// Now your viewcontroller is being viewed
}
Eu uso essa pequena extensão no Swift 5 , que mantém simples e fácil verificar qualquer objeto que seja membro do UIView .
extension UIView {
var isVisible: Bool {
guard let _ = self.window else {
return false
}
return true
}
}
Então, eu apenas o uso como uma verificação simples de instrução if ...
if myView.isVisible {
// do something
}
Espero que ajude! :)