web-dev-qa-db-ja.com

View Controllerがモーダルで表示されているか、Navigation Stackにプッシュされているかを確認します

私のView Controllerコードでは、どうすれば区別できますか?

  • モーダルで提示
  • ナビゲーションスタックにプッシュ

presentingViewControllerisMovingToParentViewControllerは両方ともYESであるため、あまり役に立ちません。

物事を複雑にしているのは、親View Controllerがモーダルであることがあり、その上にチェック対象のView Controllerがプッシュされることです。

私の問題は、HtmlViewControllerUINavigationControllerに埋め込んでから表示することです。それが、私自身の試みと以下の良い答えがうまくいかなかった理由です。

HtmlViewController*     termsViewController = [[HtmlViewController alloc] initWithDictionary:dictionary];
UINavigationController* modalViewController;

modalViewController = [[UINavigationController alloc] initWithRootViewController:termsViewController];
modalViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:modalViewController
                   animated:YES
                 completion:nil];

モーダルであるかどうかを判断するのではなく、View Controllerに伝えた方が良いと思います。

96
meaning-matters

塩の粒で取り、テストしませんでした。

- (BOOL)isModal {
     if([self presentingViewController])
         return YES;
     if([[[self navigationController] presentingViewController] presentedViewController] == [self navigationController])
         return YES;
     if([[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]])
         return YES;

    return NO;
 }
113
ColdLogic

1つのメソッドを見落としていました:isBeingPresented

isBeingPresentedは、View Controllerが表示されている場合はtrue、プッシュされている場合はfalseです。

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if ([self isBeingPresented]) {
        // being presented
    } else if ([self isMovingToParentViewController]) {
        // being pushed
    } else {
        // simply showing again because another VC was dismissed
    }
}
68
rmaddy

In Swift

// MARK: - UIViewController implementation

extension UIViewController {

    var isModal: Bool {

        let presentingIsModal = presentingViewController != nil
        let presentingIsNavigation = navigationController?.presentingViewController?.presentedViewController == navigationController
        let presentingIsTabBar = tabBarController?.presentingViewController is UITabBarController

        return presentingIsModal || presentingIsNavigation || presentingIsTabBar
    }
}
66
King-Wizard

self.navigationController!= nilは、ナビゲーションスタック内にあることを意味します。

ナビゲーションコントローラーがモーダルモードで表示されているときに現在のビューコントローラーがプッシュされる場合を処理するために、現在のビューコントローラーがナビゲーションスタックのルートコントローラーであるかどうかを確認するコードをいくつか追加しました。

extension UIViewController{
func isModal() -> Bool {

    if let navigationController = self.navigationController{
        if navigationController.viewControllers.first != self{
            return false
        }
    }

    if self.presentingViewController != nil {
        return true
    }

    if self.navigationController?.presentingViewController?.presentedViewController == self.navigationController  {
        return true
    }

    if self.tabBarController?.presentingViewController is UITabBarController {
        return true
    }

    return false
   }
}
20
Jibeex

Swift
プッシュされたtrueが提示されたUIViewControllerスタックにある場合、isModal()UINavigationControllerを返すときに、以前の回答で言及された問題に対処するソリューションがあります。

extension UIViewController {
    var isModal: Bool {
        if let index = navigationController?.viewControllers.index(of: self), index > 0 {
            return false
        } else if presentingViewController != nil {
            return true
        } else if navigationController?.presentingViewController?.presentedViewController == navigationController  {
            return true
        } else if tabBarController?.presentingViewController is UITabBarController {
            return true
        } else {
            return false
        }
    }
}

これは今のところうまくいきます。最適化する場合は、共有してください。

17
Jonauz

Swift 4

var isModal: Bool {
    return presentingViewController != nil ||
           navigationController?.presentingViewController?.presentedViewController === navigationController ||
           tabBarController?.presentingViewController is UITabBarController
}
12

ここで多くの人が示唆しているように、「チェック」メソッドはすべての場合にうまく機能しないと考えています。私のプロジェクトでは、それを手動で管理するソリューションを考え出しました。ポイントは、私たちは通常、自分でプレゼンテーションを管理します-これは舞台裏で起こることではなく、内省する必要があります。

DEViewController.hファイル:

#import <UIKit/UIKit.h>

// it is a base class for all view controllers within a project
@interface DEViewController : UIViewController 

// specify a way viewcontroller, is presented  by another viewcontroller
// the presented view controller should manually assign the value to it
typedef NS_ENUM(NSUInteger, SSViewControllerPresentationMethod) {
    SSViewControllerPresentationMethodUnspecified = 0,
    SSViewControllerPresentationMethodPush,
    SSViewControllerPresentationMethodModal,
};
@property (nonatomic) SSViewControllerPresentationMethod viewControllerPresentationMethod;

// other properties/methods...
@end

プレゼンテーションは次の方法で管理できます。

ナビゲーションスタックにプッシュ:

// DETestViewController inherits from DEViewController
DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodPush;
[self.navigationController pushViewController:vc animated:YES];

ナビゲーションでモーダルに表示:

DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodModal;
UINavigationController *nav = [[UINavigationController alloc]
                               initWithRootViewController:vc];
[self presentViewController:nav animated:YES completion:nil];

モーダル表示:

DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodModal;
[self presentViewController:vc animated:YES completion:nil];

また、DEViewControllerでは、前述のプロパティがSSViewControllerPresentationMethodUnspecifiedと等しい場合、「checking」にフォールバックを追加できます。

- (BOOL)isViewControllerPushed
{
    if (self.viewControllerPresentationMethod != SSViewControllerPresentationMethodUnspecified) {
        return (BOOL)(self.viewControllerPresentationMethod == SSViewControllerPresentationMethodPush);
    }

    else {
        // fallback to default determination method
        return (BOOL)self.navigationController.viewControllers.count > 1;
    }
}
3
Yevhen Dubinin

モーダルで表示するすべてのviewControllerが新しいnavigationController内にラップされていると仮定すると(これは常に実行する必要があります)、VCにこのプロパティを追加できます。

private var wasPushed: Bool {
    guard let vc = navigationController?.viewControllers.first where vc == self else {
        return true
    }

    return false
}
3
Demosthese

コントローラーがプッシュされたことを検出するには、または必要な場所で以下のコードを使用するだけではありません。

if ([[[self.parentViewController childViewControllers] firstObject] isKindOfClass:[self class]]) {

    // Not pushed
}
else {

    // Pushed
}

このコードが誰にも役立つことを願っています...

2

self.navigationController != nilは、ナビゲーションスタック内にあることを意味します。

2
Daniel
if navigationController.presentingViewController != nil {
    // Navigation controller is being presented modally
}
0
Kirill Kudaev

IOS 5.0以降を使用している場合は、このコードを使用してください

-(BOOL)isPresented
{
if ([self isBeingPresented]) {
    // being presented
     return YES;
} else if ([self isMovingToParentViewController]) {
    // being pushed
     return NO;
} else {
    // simply showing again because another VC was dismissed
     return NO;
}

}

0
Shahbaz Abbasi
if let navigationController = self.navigationController, navigationController.isBeingPresented {
    // being presented
}else{
    // being pushed
}
0
mkto