UIViewControllerのビューが表示されているかどうかを確認する方法


回答:


1098

ビューが現在表示されている場合、ビューのウィンドウプロパティは非nilなので、ビューコントローラーでメインビューを確認します。

viewメソッドを呼び出すと、ビューがロードされます(ロードされていない場合)。これは不要であり、望ましくない場合があります。それがすでにロードされているかどうかを最初に確認することをお勧めします。この問題を回避するために、isViewLoadedへの呼び出しを追加しました。

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

iOS9以降、簡単になりました:

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

または、ビューコントローラーを管理するUINavigationControllerがある場合は、代わりにvisibleViewControllerプロパティを確認できます。


11
UINavigationControllerのvisibleViewControlleeプロパティの1つの問題は、visibleViewControllerがモーダルビューコントローラーを提示する場合です。その場合、モーダルビューはvisibleViewControllerになり、望ましくない場合があります。それをどのように扱いますか?
Moshe

12
これはおそらく誰にとっても明白ですが、私にとってコードはself.isViewLoaded && self.view.windowでなければなりませんでした
JeffB6688

85
このソリューションを他の状況に一般化する際は注意してください。たとえば、UIPageViewControllerを使用している場合、現在のページではないUIViewControllersのビューは、画面外にレンダリングされるため、nil以外のウィンドウプロパティがまだある可能性があります。この場合、viewDidAppearおよびviewDidDisappearで設定される独自の「isCurrentlyVisible」プロパティを作成することに成功しました。
evanflash 2014年

4
その場合は@Mosheを使用しますtopViewController
ma11hew28 14年

3
この回答は実際の可視性については何も述べていないことに注意してください。たとえば、アプリがバックグラウンドにある場合、ビューは実際には表示されませんが、IFステートメントはYESを返します。
Marek J.

89

これは、UIViewControllerカテゴリとしての@progrmrのソリューションです。

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

47

上記のソリューションにはいくつかの問題があります。たとえばを使用している場合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;
}

1
これはxCode 7.1.1でも同じですか?UISplitViewControllerのマスターが、viewController.view.windowに対してNOを返しています。私は何か悪いことをしているかもしれませんが、これは事実だと確信しています。
SAHM 2016年

44

答えの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
}

理由はわかりませんが、self.view.window!= nilを実行すると、self.isViewLoadedがtrueの場合でも機能しないことがわかりました。削除すると、正常に動作します。
Micah Montoya

これは、viewDidAppearでのみ機能しました。これをviewWillAppearに追加すると、self.view.window!= nilは常にnilになりました
ランスサマリア

29

全画面表示以上またはコンテキスト表示以上のモーダルプレゼンテーションの場合、「可視」とは、ビューコントローラースタックの上にあるか、表示されているだけで別のビューコントローラーで覆われていることを意味します。

「トップビューコントローラーである」というビューコントローラーが「表示されている」とまったく異なるかどうかを確認するには、ビューコントローラーのナビゲーションコントローラーのビューコントローラースタックを確認する必要があります。

この問題を解決するためのコードを書きました。

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

いい投稿です!FYI isViewLoadedはSwift 3.0以降のプロパティです。
Yuchen Zhong 2017

28

UITabBarControllerselectedViewControllerプロパティを使用します。タブバーコントローラーに接続されているすべてのビューコントローラーにはtabBarControllerプロパティセットがあるため、任意のビューコントローラーのコード内から行うことができます。

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

2
ビューコントローラーがナビゲーションコントローラー内に含まれ、そのコントローラーがタブバーコントローラーに追加されている場合、これは機能しません。selectedViewControllerを呼び出すと、現在のビューコントローラではなく、ナビゲーションコントローラが返されます。
アントンホルムベルク、

2
:その場合に@AntonHolmberg、このような目に見えるビューコントローラを取得((UINavigationController *)self.tabBarController.selectedViewController).visibleViewController
ma11hew28

または、ここまで行った場合は、「self.tabBarController.selectedIndex」プロパティを使用します。
Vladimir Shutyuk

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

私の目的のために、コンテナービューコントローラーのコンテキストでは、

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

うまくいきます。


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
}

2
この方法は、ナビゲーションコントローラーが使用可能な場合、受け入れられた回答よりも信頼できることがわかりました。これは次のように短縮できます:if([self.navigationController.visibleViewController isKindOfClass:[self class]]){
Darren

3

モーダル表示ビューコントローラーに使用したアプローチは、表示コントローラーのクラスをチェックすることでした。提示されたView Controllerがそうであった場合、ViewController2私はいくつかのコードを実行します。

UIViewController *vc = [self presentedViewController];

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

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)viewDidLoad0 -(void)viewDidAppear:(BOOL)animatedが取得され、1を取得した後にこれを呼び出すと

これが誰かを助けることを願っています。ありがとう!乾杯。


3

ナビゲーションコントローラを使用していて、アクティブ最上位のコントローラにいるかどうかを知りたい場合は、次のコマンドを使用します。

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

この回答は@mattdipasqualeに基づいていますのコメントにます。

より複雑なシナリオがある場合は、上記の他の回答を参照してください。


アプリがバックグラウンドで実行され、その後フォアグラウンドで実行される場合、これは呼び出されません。ビューコントローラーがユーザーに表示されるかどうかを確認できるソリューションを探しています。ユーザーは数日間アプリをバックグラウンドで実行でき、それがフォアグラウンドで戻ってきたら、UIを更新したいと思います。お手伝いできるかどうかお知らせください。
2018年


0

これは、ビューコントローラーが現在表示されているコントローラーかどうかを確認するために必要でした。表示されたビューコントローラーがあるかどうかを確認するか、ナビゲーターを介してプッシュしました。誰かがそのような解決策を必要とする場合に備えて投稿します。

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

0

私はこの小さな拡張機能をSwift 5で使用しています。これにより、UIViewのメンバーであるオブジェクトを簡単かつ簡単に確認できます。

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

次に、単純なifステートメントチェックとして使用します...

if myView.isVisible {
    // do something
}

お役に立てば幸いです。:)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.