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

时间:2010-05-05 23:25:10

标签: ios uiview uiviewcontroller

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

17 个答案:

答案 0 :(得分:1004)

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

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

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

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

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

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

答案 1 :(得分:88)

这是@ 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

答案 2 :(得分:44)

上述解决方案存在一些问题。例如,如果您使用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 :(得分:42)

对于那些寻找 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
}

答案 4 :(得分:27)

您想使用UITabBarController的{​​{1}}媒体资源。附加到选项卡栏控制器的所有视图控制器都具有selectedViewController属性集,因此您可以在任何视图控制器的代码中添加:

tabBarController

答案 5 :(得分:24)

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

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

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

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

答案 6 :(得分:12)

我根据@ progrmr的回答迅速进行了扩展。

它可以让您轻松检查UIViewController是否在屏幕上,如下所示:

if someViewController.isOnScreen {
    // Do stuff here
}

扩展名:

//
//  UIViewControllerExtension.swift
//

import UIKit

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

答案 7 :(得分:7)

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

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

效果很好。

答案 8 :(得分:3)

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

UIViewController *vc = [self presentedViewController];

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

答案 9 :(得分:3)

如果您正在使用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
}

答案 10 :(得分: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是否出现。

答案 11 :(得分: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。

希望这有助于某人。谢谢!欢呼声。

答案 12 :(得分:3)

如果您使用的是导航控制器并且只想知道您是否在活动最顶层控制器中,请使用:

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

此答案基于@mattdipasquale的评论。

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

答案 13 :(得分:2)

您可以通过window属性

进行检查
if(viewController.view.window){

// view visible

}else{

// no visible

}

答案 14 :(得分:1)

如果该视图已经在窗口层次结构堆栈中,则会显示该视图。 因此我们可以扩展该类的功能。

extension UIViewController {
  var isViewAppeared: Bool { viewIfLoaded?.isAppeared == true }
}

extension UIView {
  var isAppeared: Bool { window != nil }
}

答案 15 :(得分:0)

我需要它来检查视图控制器是否为当前查看的控制器,我是通过检查是否存在任何显示的视图控制器或通过导航器来完成的,如果有人需要这样的解决方案,我会发布它:

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

答案 16 :(得分:0)

我在 Swift 5 中使用了这个小的扩展名,它使检查 UIView 成员中的任何对象变得简单而容易。

extension UIView {
    var isVisible: Bool {
        guard let _ = self.window else {
            return false
        }
        return true
    }
}

然后,我将其用作简单的if语句检查...

if myView.isVisible {
    // do something
}

希望对您有所帮助! :)