web-dev-qa-db-fra.com

Comment savoir si la vue UIViewController est visible

J'ai une application de barre d'onglets, avec de nombreuses vues. Existe-t-il un moyen de savoir si une UIViewController particulière est actuellement visible à l'intérieur de la UIViewController? (cherche une propriété)

532
Rob Bonner

La vue propriété de la fenêtre est non nulle si une vue est actuellement visible. Vérifiez donc la vue principale dans le contrôleur de vue:

L'appel de la méthode view entraîne le chargement de la vue (si elle n'est pas chargée), ce qui est inutile et peut être indésirable. Il serait préférable de vérifier d'abord pour voir s'il est déjà chargé. J'ai ajouté l'appel à isViewLoaded pour éviter ce problème.

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

Ou, si vous avez un UINavigationController gérant les contrôleurs de vue, vous pouvez plutôt vérifier sa propriété visibleViewController .

De plus, dans Swift sur iOS 9 (ou version ultérieure):

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

Voici la solution de @ progrmr en tant que catégorie 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
89
ma11hew28

Les solutions ci-dessus posent quelques problèmes. Si vous utilisez, par exemple, un UISplitViewController, la vue principale renverra toujours la valeur true pour

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

Au lieu de cela, adoptez cette approche simple qui semble bien fonctionner dans la plupart, sinon dans tous les cas:

- (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;
}
45
vincentjames501

Pour ceux qui recherchent une version Swift 2.2:

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

et Swift:

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

Vous voulez utiliser la propriété UITabBarController 'selectedViewController. Tous les contrôleurs de vue attachés à un contrôleur de barre de tabulation ont une propriété tabBarController, vous pouvez donc, à partir de n'importe quel code du contrôleur de vue:

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

Pour une présentation modale en plein écran ou en contexte, "est visible" peut signifier qu'elle se trouve au-dessus de la pile du contrôleur de vue ou juste visible, mais qu'elle est couverte par un autre contrôleur de vue.

Pour vérifier si le contrôleur de vue "est le contrôleur de vue de dessus" est assez différent de "est visible", vous devez vérifier la pile de contrôleur de vue du contrôleur de navigation du contrôleur de vue.

J'ai écrit un morceau de code pour résoudre ce problème:

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
        }
    }
}
25
WeZZard

J'ai créé une extension Swift sur la base de la réponse de @ progrmr.

Il vous permet de vérifier facilement si un UIViewController apparaît à l'écran de la manière suivante:

if someViewController.isOnScreen {
    // Do stuff here
}

L'extension:

//
//  UIViewControllerExtension.Swift
//

import UIKit

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

Pour mes besoins, dans le contexte d'un contrôleur de vue de conteneur, j'ai constaté que

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

fonctionne bien.

7
Chris Prince

J'ai trouvé ces fonctions dans 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);

Peut-être que les fonctions ci-dessus peuvent détecter le ViewController est apparu ou non.

3
AechoLiu

si vous utilisez un contrôleur UINavigation et souhaitez également gérer les vues modales, voici ce que j'utilise:

#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
}
3
MrTristan

Si vous utilisez un contrôleur de navigation et que vous voulez juste savoir si vous êtes dans le actif et en haut contrôleur, puis utilisez:

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

Cette réponse est basée sur le commentaire de @ mattdipasquale .

Si vous avez un scénario plus compliqué, reportez-vous aux autres réponses ci-dessus.

3
phatmann

L'approche que j'ai utilisée pour un contrôleur de vue présenté modal consistait à vérifier la classe du contrôleur présenté. Si le contrôleur de vue présenté était ViewController2 alors j'exécuterais du code.

UIViewController *vc = [self presentedViewController];

if ([vc isKindOfClass:[ViewController2 class]]) {
    NSLog(@"this is VC2");
}
3
wigging

XCode 6.4, pour iOS 8.4, compatible ARC

Il y a évidemment beaucoup de façons de le faire. Celui qui a fonctionné pour moi est le suivant ...

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

Ceci peut être utilisé dans n’importe quel contrôleur de vue de la manière suivante,

[self.view.window isKeyWindow]

Si vous appelez cette propriété dans -(void)viewDidLoad, vous obtenez 0, puis si vous appelez cette propriété après -(void)viewDidAppear:(BOOL)animated, vous obtenez 1.

J'espère que ça aide quelqu'un. Merci! À votre santé.

3
serge-k

vous pouvez le vérifier par la propriété window

if(viewController.view.window){

// view visible

}else{

// no visible

}
2
Saad Ur Rehman

J'avais besoin de cela pour vérifier si le contrôleur de vue est le contrôleur actuellement visualisé. Je l'ai fait en vérifiant s'il y avait un contrôleur de vue présenté ou poussé dans le navigateur, je le publie au cas où quelqu'un aurait besoin d'une telle solution:

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