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

我有一个tabbar应用程序,许多意见。 有没有办法知道一个特定的UIViewController目前是否可以从UIViewController中看到? (寻找财产)

如果视图当前可见,视图的窗口属性是非零,所以检查视图控制器中的主视图:

[编辑]调用view方法会导致视图加载(如果没有加载),这是不必要的,可能是不可取的。 先检查一下是否已经加载好了。 我已经添加了调用isViewLoaded来避免这个问题。

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

或者,如果您有一个pipe理视图控制器的UINavigationController,则可以改为查看其visibleViewController属性。

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

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

这里是@ progrmr的解决scheme作为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 

上述解决scheme有几个问题。 例如,如果使用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; } 

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

你想使用UITabBarControllerselectedViewController属性。 连接到标签栏控制器的所有视图控制器都有一个tabBarController属性集,因此您可以从任何视图控制器的代码中:

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

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

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

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

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

我根据@ progrmr的回答做了一个快速的扩展。

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

 if someViewController.isOnScreen { // Do stuff here } 

扩展名:

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

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

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

效果很好。

如果你正在使用一个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 } 

你可以通过window属性来检查它

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

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

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

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。

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

如果您正在使用导航控制器,只想知道您是否在主动最上层控制器中,请使用:

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

这个答案是基于@mattdipasquale的评论。

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

我在UIViewController.hfind了这些函数。

 /* 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是否出现。

由于UIAlertController是从UIViewController派生的,所以你可以使用isBeingPresented

 if (alertController.isBeingPresented) { // alert is showing }