首页 文章

如何判断UIViewController的视图是否可见

提问于
浏览 1099
491

我有一个标签栏应用程序,有很多视图 . 有没有办法知道 UIViewController 当前是否可以看到特定的 UIViewController ? (寻找房产)

15 回答

  • 964

    我根据@ progrmr的回答快速扩展了 .

    它允许您轻松检查 UIViewController 是否在屏幕上,如下所示:

    if someViewController.isOnScreen {
        // Do stuff here
    }
    

    扩展名:

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

    如果您正在使用UINavigationController并且还想处理模态视图,我使用以下内容:

    #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
    }
    
  • 41

    为了我的目的,在容器视图控制器的上下文中,我发现了

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

    效果很好 .

  • 40

    我需要这个来检查视图控制器是否是当前查看的控制器,我通过检查是否有任何呈现的视图控制器或通过导航器推送它,我发布它以防任何人需要这样的解决方案:

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

    我用于模态呈现视图控制器的方法是检查所呈现的控制器的类 . 如果呈现的视图控制器是 ViewController2 ,那么我将执行一些代码 .

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

    您想使用 UITabBarControllerselectedViewController 属性 . 连接到选项卡栏控制器的所有视图控制器都具有 tabBarController 属性集,因此您可以在任何视图控制器的代码中:

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

    你可以通过 window 属性查看它

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

    对于超全屏或过度上下文模式显示,“可见”可能意味着它位于视图控制器堆栈的顶部或仅可见但被另一个视图控制器覆盖 .

    要检查视图控制器“是顶视图控制器”是否与“可见”完全不同,您应该检查视图控制器的导航控制器的视图控制器堆栈 .

    我写了一段代码来解决这个问题:

    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
            }
        }
    }
    
  • 3

    如果视图当前可见,则视图的window property为非零,因此请检查视图控制器中的主视图:

    [EDIT] 调用view方法会导致视图加载(如果未加载),这是不必要的,也可能是不合需要的 . 最好首先检查它是否已经加载 . 我已经添加了对isViewLoaded的调用以避免这个问题 .

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

    或者,如果您有管理视图控制器的UINavigationController,则可以检查其visibleViewController属性 .

    另外,在iOS 9(或更高版本)的Swift中:

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

    这里's @progrmr'的解决方案为 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
    
  • 3

    上述解决方案存在一些问题 . 例如,如果您使用的是 UISplitViewController ,则主视图将始终返回true

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

    相反,采取这种简单的方法似乎在大多数情况下(如果不是所有情况)都能正常工作:

    - (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;
    }
    
  • 3

    我在 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);
    

    也许以上功能可以检测 ViewController 是否出现 .

  • 3

    XCode 6.4,适用于iOS 8.4,启用了ARC

    显然有很多方法可以做到这一点 . 对我有用的是以下......

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

    这可以通过以下方式在任何视图控制器中使用,

    [self.view.window isKeyWindow]
    

    如果你在 -(void)viewDidLoad 中调用此属性,则得到0,然后如果在 -(void)viewDidAppear:(BOOL)animated 之后调用此属性,则得到1 .

    希望这有助于某人 . 谢谢!干杯 .

  • 2

    如果您正在使用导航控制器并且只想知道您是否在 activetopmost 控制器中,那么使用:

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

    这个答案基于@mattdipasquale的评论 .

    如果您有更复杂的情况,请参阅上面的其他答案 .

  • 0

    对于那些寻找 Swift 2.2 版本答案的人:

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

    Swift 3

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

相关问题