[英]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.