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

Rob*_*ner 543 uiviewcontroller uiview uiwindow ios

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

pro*_*rmr 1044

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

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

if (viewController.isViewLoaded && viewController.view.window) {
    // viewController is visible
}
Run Code Online (Sandbox Code Playgroud)

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

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

if viewController.viewIfLoaded?.window != nil {
    // viewController is visible
}
Run Code Online (Sandbox Code Playgroud)

  • 将此解决方案概括为其他情况时要小心.例如,如果您正在使用UIPageViewController,那么不是当前页面的UIViewControllers视图可能仍然具有非零窗口属性,因为它们是在屏幕外呈现的.在这种情况下,我已成功制作了自己的'isCurrentlyVisible'属性,该属性在viewDidAppear和viewDidDisappear中设置. (77认同)
  • 这对每个人来说都很明显,但对我来说,代码必须是self.isViewLoaded && self.view.window (12认同)
  • UINavigationController的visibleViewControllee属性的一个问题是你的visibleViewController呈现模态视图控制器的情况.在这种情况下,模态视图变为visibleViewController,这可能是不合需要的.你会怎么处理? (11认同)
  • @Moshe在这种情况下,使用`topViewController`. (4认同)
  • 请注意,这个答案并没有说明真正的可见性。例如,如果应用程序在后台,IF 语句将说 YES 而视图实际上不可见。 (4认同)

ma1*_*w28 89

这是@ 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
Run Code Online (Sandbox Code Playgroud)


小智 46

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

if(viewController.isViewLoaded && viewController.view.window) {
    //Always true for master view in split view controller
}
Run Code Online (Sandbox Code Playgroud)

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

- (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;
}
Run Code Online (Sandbox Code Playgroud)


Ben*_*min 44

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

if self.isViewLoaded() && (self.view.window != nil) {
     // viewController is visible
}
Run Code Online (Sandbox Code Playgroud)

斯威夫特3:

if self.isViewLoaded && (self.view.window != nil) {
         // viewController is visible
}
Run Code Online (Sandbox Code Playgroud)


exe*_*r21 28

你想使用UITabBarControllerselectedViewController属性.附加到选项卡栏控制器的所有视图控制器都有一个tabBarController属性集,因此您可以从任何视图控制器的代码中:

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

  • 如果视图控制器包含在导航控制器中并且该控制器已添加到选项卡栏控制器中,则此操作无效.对selectedViewController的调用将返回导航控制器而不是当前视图控制器. (2认同)
  • @AntonHolmberg在这种情况下,得到这样的可见视图控制器:`(((UINavigationController*)self.tabBarController.selectedViewController).visibleViewController` (2认同)

WeZ*_*ard 26

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

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

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

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Bes*_*esi 12

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

它允许您轻松检查是否UIViewController在屏幕上是这样的:

if someViewController.isOnScreen {
    // Do stuff here
}
Run Code Online (Sandbox Code Playgroud)

扩展名:

//
//  UIViewControllerExtension.swift
//

import UIKit

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


Chr*_*nce 7

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

- (BOOL)isVisible {
    return (self.isViewLoaded && self.view.window && self.parentViewController != nil);
}
Run Code Online (Sandbox Code Playgroud)

效果很好.


val*_*u17 6

我在Swift 5中使用这个小扩展,它可以简单轻松地检查UIView成员的任何对象。

extension UIView {
    var isVisible: Bool {
        guard let _ = self.window else {
            return false
        }
        return true
    }
}
Run Code Online (Sandbox Code Playgroud)

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

if myView.isVisible {
    // do something
}
Run Code Online (Sandbox Code Playgroud)

我希望它有帮助!:)


dim*_*iax 5

好的一点是,如果视图已经在窗口层次结构堆栈中,则会出现该视图。因此我们可以扩展我们的类来实现此功能。

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

extension UIView {
  var isAppeared: Bool { window != nil }
}
Run Code Online (Sandbox Code Playgroud)