簡體   English   中英

如何識別出呈現UIViewController

[英]How to identify that an UIViewController is presented

我創建了一個UIViewController子類,它可以在UINavigationController的導航堆棧中推送,也可以從任何UIViewController呈現(模態)。 我需要確定是否顯示了我的視圖控制器,如果顯示,我需要在視圖控制器的頂部添加一個帶有關閉按鈕的工具欄。 (否則,如果將其推入導航堆棧,則會添加默認關閉按鈕,使用該用戶可以返回。)

在UIViewController子類內部的所有可用版本中說4.3,5.0,直到6.0,如果滿足以下條件,我可以假設視圖控制器是以模態方式呈現的。

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

與iOS 5,獲得的UIViewController命名一個只讀屬性presentingViewController ,替換較舊的語義parentViewController (現在描述遏制 )。 當視圖控制器需要訪問呈現它的視圖控制器時,可以使用此屬性 - 注意:如果您是API新手,這通常會超出您的期望!

此外,引入isBeingPresented屬性幾乎可以解決您當前所處的情況。在視圖控制器的viewWillAppear:檢查此屬性viewWillAppear:

更新

我認為你似乎也瞄准了iOS 4.3:
在這種情況下,你需要使用if ([self respondsToSelector:…])來保護對isBeingPresented的調用,然后你可以在else塊中檢查parentViewController是否不是nil。

另一種向后兼容的方法可能是覆蓋+resolveInstanceMethod:在運行時為-isBeingPresented添加實現。 這將使您的呼叫站點保持干凈,只要您放棄古老的iOS支持,您就可以擺脫運行時魔術;-)

但是請注意,有這樣的邊緣情況,並且在iOS <5上運行時也是初始方法:

視圖控制器可以包含在任何其他視圖控制器中,包括導航控制器。 當最后一種情況發生時,你運氣不好: parentViewController將為nil ,而navigationController不會 您可以嘗試添加大量笨拙的代碼來緩解舊iOS中的這種限制......或者您可以放手。

我使用此代碼來檢查是否顯示了UIViewController。

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

我有一個類似的情況,但我提出的視圖控制器包含在它自己的導航控制器中 因此在該視圖控制器中,當我需要確定是否添加關閉按鈕與后退按鈕時, 我只需檢查導航控制器堆棧大小 如果顯示屏幕,則堆棧大小應為1(需要關閉按鈕)...如果使用現有導航控制器推送,則堆棧大小將大於1(需要后退按鈕)。

BOOL presented = [[self.navigationController viewControllers] count] == 1;

為了處理這種行為,我通常在viewWillAppear / viewWillDisappear方法中設置/重置BOOL切換它。

順便說一下,你的測試條件似乎不正確。 我想你應該用

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

為什么不能一直將工具欄添加到視圖控制器? 是否有任何情況下加載視圖但從未出現?

@saikamesh。

當您使用UINavigationController導航viewControllers時,我認為您可以使用topViewController此處為Doc )和visibleViewController再次使用Doc )來達到您的意圖。

你提到:

當它被推入導航堆棧時,將添加默認關閉按鈕,使用該用戶可以返回

如果特定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;
}

或者,您可以閱讀廣為接受的答案

:)希望有所幫助。

請檢查這種方式:

 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");
        }

    }
}

你可以這樣做,它快速而安全

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
}

您可以通過使用導航控制器中的modalViewController屬性隨時檢查是否有模態視圖控制器。 例如:

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

我沒有在這里看到一個優雅的答案:

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

信用:基於這個要點

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

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

如果是我,我將有一個自定義init方法,並在創建vc時使用它。

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

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

正如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];
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM