web-dev-qa-db-ja.com

UIViewControllerが提示されていることを識別する方法

UINavigationControllerのナビゲーションスタックにプッシュするか、任意のUIViewControllerから表示(モーダル)できるUIViewControllerサブクラスを作成しました。 View Controllerが表示されているかどうかを確認する必要があります。表示されている場合は、View Controllerの上部に閉じるボタンのあるツールバーを追加する必要があります。 (そうでない場合は、ナビゲーションスタックにプッシュされると、ユーザーが戻ることができるデフォルトの閉じるボタンが追加されます。)

すべての利用可能なバージョンは、4.3、5.0、6.0まで、UIViewControllerサブクラス内から、次の条件が満たされている場合、View Controllerが(モーダルに)提示されると仮定できますか?.

if(self.parentViewController == nil || self.navigationController == nil)
25
saikamesh

IOS 5では、UIViewControllerはpresentingViewControllerという名前の読み取り専用プロパティを取得しました。これは、parentViewControllerの古いセマンティクスを置き換えます(現在はcontainment)。このプロパティは、View Controllerがそれを表示しているView Controllerに到達する必要がある場合に使用できます。注:これは、APIを初めて使用する場合、多くの場合、予想とは異なるものになります。

さらに、現在の状況のクラスをほぼ解決するためにisBeingPresentedプロパティが導入されました。ViewControllerの_viewWillAppear:_でこのプロパティを確認してください。

更新

あなたもiOS 4.3をターゲットにしているようだということを私は読み直しました:
その場合、isBeingPresentedへの呼び出しをif ([self respondsToSelector:…])でガードする必要があります。その後、elseブロックでparentViewControllerがなし.

後方互換性への別のアプローチは、実行時に_+resolveInstanceMethod:_をオーバーライドして_-isBeingPresented_の実装を追加することです。これにより、呼び出し元のサイトがクリーンになり、古いiOSサポートを手放すとすぐにランタイムマジックがなくなります;-)

ただし、これにはEdgeのケースがあることに注意してください。iOS<5で実行する場合は、最初のアプローチも同様です。

View Controllerは、Navigation Controllerを含む他のView Controllerに含まれて表示できます。最後のケースが発生すると、運が悪くなります。parentViewControllernilになりますが、navigationControllernotになります。古いiOSでのこの制限を緩和するために扱いにくいコードのゴブを追加することを試みることができます...または、単に放すことができます。

34
danyowdee

このコードを使用して、UIViewControllerが表示されるかどうかを確認します。

if (uiviewcontroller.presentingViewController != nil) {
   // do something
}
10
Evelyn Loo

同様のケースがありましたが、提示したView Controllerは独自のNavigation Controllerにラップされていますです。そのため、そのView Controllerでは、閉じるボタンと戻るボタンを追加するかどうかを判断する必要があるときに、Navigation Controllerのスタックサイズを確認するだけですです。画面が表示される場合、スタックサイズは1(閉じるボタンが必要)である必要があります。既存のナビゲーションコントローラーを使用してプッシュされる場合、スタックサイズは1より大きくなります(戻るボタンが必要)。

BOOL presented = [[self.navigationController viewControllers] count] == 1;
8
Martin M Reed

この種の動作を処理するには、通常、viewWillAppear/viewWillDisappearメソッドでBOOLをトグルするように設定/リセットします。

ところで、テスト条件は間違っているようです。使うべきだと思う

if(self.parentViewController != nil || self.navigationController != nil)

View Controllerにツールバーを常に追加できないのはなぜですか?ビューはロードされているが表示されない場合はありますか?

7
Gl0ub1l

@saikamesh。

UINavigationControllerを使用してviewControllerをナビゲートするときに、topViewControllerDoc here )およびvisibleViewControllerDoc again )を使用してあなたの意図に到達します。

あなたはそれについて言及します:

ナビゲーションスタックにプッシュされると、ユーザーが戻ることができるデフォルトの閉じるボタンが追加されます。

特定のUIViewControllerのインスタンスが重要な場合、共有シングルトンインスタンスを作成し、グローバル表示フラグを提供することをお勧めします。

id specificVC = [SpecificViewController sharedInstance];
if (specificVC.isPushed) {
    [self.navController popToViewController:specificVC animated:YES];
}

そして、それが提示されているかどうかを確認するには:

if ([self.navController.visibleViewController isKindOfClass:[SpecificViewController class]]) {
    // Hide or add close button
    self.isPresented = YES;
}

または、 多く受け入れられている答え と読むことができます。

:)希望が役立ちます。

3
Jason Lee

このようにすることができます、それは速くて安全です

UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

// Find the top controller on the view hierarchy
while (topController.presentedViewController) {
    topController = topController.presentedViewController;
}

// If the top controller it is not already presented
if (![topController isKindOfClass:[YourViewController class]]) {
    // Present it
    [topController presentViewController:yourViewController animated:YES completion:nil];
}
else {
// do some stuff here
}
2

この方法を確認してください:

 for (UIViewController*vc in [self.navigationController viewControllers]) {
    if ([vc isKindOfClass: [OffersViewController class]]){ //this line also checks OffersViewController is presented or not 

        if(vc.isViewLoaded){
             NSLog(@"Yes");
        }

    }
}
2
Banker Mittal

ここでは見たことのないエレガントな答え:

// Edit: Added 2 other modal cases
extension UIViewController {
    var isModal: Bool { 
        return self.presentingViewController?.presentedViewController == self
            || (navigationController != nil && navigationController?.presentingViewController?.presentedViewController == navigationController)
            || tabBarController?.presentingViewController is UITabBarController
    }
}

クレジット: this Gist に基づく

1
AmitaiB

Navigation ControllerのmodalViewControllerプロパティを使用して、モーダルView Controllerが表示されているかどうかをいつでも確認できます。例:

   UIViewController *presentedController = self.navigationController.modalViewController;
   if (presentedController) {
      // At this point, you have a view controller presented from your navigation controller
      if ([presentedController isKindOfClass:[controllerYouWantToCheck class]]) {
         // add your toolbar/buttons/etc here
      }
   }
1
Vlad

In Swift):

if viewController.viewIfLoaded?.window != nil {
    // viewController is visible
}
1
Ali A. Jalil

それが私だったら、カスタムのinitメソッドがあり、vcを作成するときにそれを使用します。

vc = [[[MyUIViewControllerSubClass alloc] init] initWithToolbarAndCloseButton:YES];
0
ader

Martin Reed が言ったように、これが最良の方法です

            BOOL presented = [[self.navigationController viewControllers] count] == 1;
        if (presented) {
            [self dismissViewControllerAnimated:YES completion:^{
                // do whatever you need here
            }];
        }
        else {
            [self.navigationController popViewControllerAnimated:YES];
        }
0
oskarko

関数を作成するための@AmitaiB回答の小さな変更、

func isModallyPresented(tmpVC:UIViewController) -> Bool {
        return tmpVC.presentingViewController?.presentedViewController == tmpVC
            || (tmpVC.navigationController != nil && tmpVC.navigationController?.presentingViewController?.presentedViewController == tmpVC.navigationController)
            || tmpVC.tabBarController?.presentingViewController is UITabBarController
    }

次を呼び出して確認してください。

if(isModallyPresented(tmpVC:myTopVC)){
//return true if viewcontroller is presented 
}
0
HDdeveloper