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

发布于 2024-08-31 15:19:49 字数 87 浏览 8 评论 0原文

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

I have a tab bar application, with many views. Is there a way to know if a particular UIViewController is currently visible from within the UIViewController? (looking for a property)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(18

平安喜乐 2024-09-07 15:19:53

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

UIViewController *vc = [self presentedViewController];

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

The approach that I used for a modal presented view controller was to check the class of the presented controller. If the presented view controller was ViewController2 then I would execute some code.

UIViewController *vc = [self presentedViewController];

if ([vc isKindOfClass:[ViewController2 class]]) {
    NSLog(@"this is VC2");
}
貪欢 2024-09-07 15:19:53

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

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

此答案基于@mattdipasquale的评论。

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

If you are using a navigation controller and just want to know if you are in the active and topmost controller, then use:

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

This answer is based on @mattdipasquale's comment.

If you have a more complicated scenario, see the other answers above.

时光清浅 2024-09-07 15:19:53

您可以通过 window 属性检查它

if(viewController.view.window){

// view visible

}else{

// no visible

}

you can check it by window property

if(viewController.view.window){

// view visible

}else{

// no visible

}
最美的太阳 2024-09-07 15:19:53

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

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

I needed this to check if the view controller is the current viewed controller, I did it via checking if there's any presented view controller or pushed through the navigator, I'm posting it in case anyone needed such a solution:

if presentedViewController != nil || navigationController?.topViewController != self {
      //Viewcontroller isn't viewed
}else{
     // Now your viewcontroller is being viewed 
}
机场等船 2024-09-07 15:19:53

窗口:

window.isVisible
viewController.view.window?.isVisible ?? false

查看 (macOS):

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

Window:

window.isVisible
viewController.view.window?.isVisible ?? false

View (macOS):

extension NSViewController {
    var isOnScreen: Bool {
        return ( self.isViewLoaded && view.window != nil )
    }
}
陌路黄昏 2024-09-07 15:19:52

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

调用 视图 方法会导致视图加载(如果未加载),这是不必要的,而且可能是不可取的。最好先检查一下是否已经加载。我添加了对 isViewLoaded 的调用来避免这个问题。

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

自 iOS9 以来,它变得更加容易:

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

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

The view's window property is non-nil if a view is currently visible, so check the main view in the view controller:

Invoking the view method causes the view to load (if it is not loaded) which is unnecessary and may be undesirable. It would be better to check first to see if it is already loaded. I've added the call to isViewLoaded to avoid this problem.

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

Since iOS9 it has became easier:

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

Or if you have a UINavigationController managing the view controllers, you could check its visibleViewController property instead.

泪意 2024-09-07 15:19:52

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

Here's @progrmr's solution as a UIViewController category:

// 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
腻橙味 2024-09-07 15:19:52

上述解决方案存在几个问题。例如,如果您使用的是 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;
}

There are a couple of issues with the above solutions. If you are using, for example, a UISplitViewController, the master view will always return true for

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

Instead, take this simple approach which seems to work well in most, if not all cases:

- (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;
}
遮了一弯 2024-09-07 15:19:52

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

For those of you looking for a Swift 2.2 version of the answer:

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

and Swift 3:

if self.isViewLoaded && (self.view.window != nil) {
         // viewController is visible
}
み零 2024-09-07 15:19:52

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

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

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

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

For over-full-screen or over-context modal presentation, "is visible" could mean it is on top of the view controller stack or just visible but covered by another view controller.

To check if the view controller "is the top view controller" is quite different from "is visible", you should check the view controller's navigation controller's view controller stack.

I wrote a piece of code to solve this problem:

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
        }
    }
}
世态炎凉 2024-09-07 15:19:52

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

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

You want to use the UITabBarController's selectedViewController property. All view controllers attached to a tab bar controller have a tabBarController property set, so you can, from within any of the view controllers' code:

if([[[self tabBarController] selectedViewController] isEqual:self]){
     //we're in the active controller
}else{
     //we are not
}
祁梦 2024-09-07 15:19:52

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

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

if someViewController.isOnScreen {
    // Do stuff here
}

扩展名:

//
//  UIViewControllerExtension.swift
//

import UIKit

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

I made a swift extension based on @progrmr's answer.

It allows you to easily check if a UIViewController is on screen like so:

if someViewController.isOnScreen {
    // Do stuff here
}

The extension:

//
//  UIViewControllerExtension.swift
//

import UIKit

extension UIViewController{
    var isOnScreen: Bool{
        return self.isViewLoaded() && view.window != nil
    }
}
半城柳色半声笛 2024-09-07 15:19:52

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

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

效果很好。

For my purposes, in the context of a container view controller, I've found that

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

works well.

阳光的暖冬 2024-09-07 15:19:52

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

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

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

if myView.isVisible {
    // do something
}

我希望它有帮助! :)

I use this small extension in Swift 5, which keeps it simple and easy to check for any object that is member of UIView.

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

Then, I just use it as a simple if statement check...

if myView.isVisible {
    // do something
}

I hope it helps! :)

凶凌 2024-09-07 15:19:52

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

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

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

Good point that view is appeared if it's already in window hierarchy stack.
thus we can extend our classes for this functionality.

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

extension UIView {
  var isAppeared: Bool { window != nil }
}
ま柒月 2024-09-07 15:19:52

我在 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是否出现。

I found those function in 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);

Maybe the above functions can detect the ViewController is appeared or not.

月光色 2024-09-07 15:19:52

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。

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

XCode 6.4, for iOS 8.4, ARC enabled

Obviously lots of ways of doing it. The one that has worked for me is the following...

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

This can be used in any view controller in the following way,

[self.view.window isKeyWindow]

If you call this property in -(void)viewDidLoad you get 0, then if you call this after -(void)viewDidAppear:(BOOL)animated you get 1.

Hope this helps someone. Thanks! Cheers.

滴情不沾 2024-09-07 15:19:52

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

if you're utilizing a UINavigationController and also want to handle modal views, the following is what i use:

#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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文