Iphone 如何识别是否显示UIViewController

Iphone 如何识别是否显示UIViewController,iphone,ios,objective-c,uiviewcontroller,modalviewcontroller,Iphone,Ios,Objective C,Uiviewcontroller,Modalviewcontroller,我已经创建了一个UIViewController子类,它可以被推送到UINavigationController的导航堆栈中,也可以从任何UIViewController(以模式)呈现。我需要确定是否显示视图控制器,如果显示,我需要在视图控制器顶部添加一个带有关闭按钮的工具栏。(否则,如果在导航堆栈中按下该按钮,则会添加默认的关闭按钮,用户可以使用该按钮返回。) 在所有可用的版本中,比如4.3、5.0到6.0,从UIViewController子类内部,如果满足以下条件,我可以假设视图控制器(以

我已经创建了一个UIViewController子类,它可以被推送到UINavigationController的导航堆栈中,也可以从任何UIViewController(以模式)呈现。我需要确定是否显示视图控制器,如果显示,我需要在视图控制器顶部添加一个带有关闭按钮的工具栏。(否则,如果在导航堆栈中按下该按钮,则会添加默认的关闭按钮,用户可以使用该按钮返回。)

在所有可用的版本中,比如4.3、5.0到6.0,从UIViewController子类内部,如果满足以下条件,我可以假设视图控制器(以模式)被显示

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

为了处理这种行为,我通常设置/重置一个BOOL,并在viewWillExample/viewWillEnglishe方法中对其进行切换

顺便说一下,您的测试条件似乎不正确。我认为你应该使用

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

为什么不能始终将工具栏添加到视图控制器?是否存在视图被加载但从未显示的情况?

如果是我,我会有一个自定义的init方法,并在创建vc时使用它

vc = [[[MyUIViewControllerSubClass alloc] init] initWithToolbarAndCloseButton: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");
        }

    }
}
@塞卡迈什

当您使用UINavigationController来导航ViewController时,我认为您可以使用
topViewController
()和
visibleViewController
()来达到您的目的

你提到:

当它被推入导航堆栈时,默认的关闭按钮 将被添加,通过使用,用户可以返回

若特定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;
}
或者,你可以阅读


:)希望有帮助。

通过使用导航控制器中的modalViewController属性,您可以随时检查是否显示了模态视图控制器。 例:


在iOS 5中,UIViewController获得了一个名为
presentingViewController
的只读属性,该属性替换了
parentViewController
的旧语义(现在描述包含)。当视图控制器需要访问显示它的视图控制器时,可以使用此属性-注意:如果您是API新手,这通常会超出您的预期

此外,
isBeingPresented
属性的引入基本上解决了您当前所处的情况。在视图控制器的
视图中检查此属性将显示:

更新 我认为你似乎也将iOS 4.3作为目标:
在这种情况下,您需要使用
if([self respondsToSelector:…])
来保护对
isBeingPresented的调用,然后可以在
else
块中检查parentViewController是否为nil

另一种实现向后兼容性的方法可能是重写
+resolveInstanceMethod:
,以便在运行时为
-isBeingPresented
添加一个实现。这将使您的呼叫站点保持干净,一旦您放弃古老的iOS支持,您就可以摆脱运行时魔法;-)


不过,请注意,在iOS上运行时,存在一些边缘情况,您也可以使用初始方法我使用此代码检查是否显示UIViewController

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

我有一个类似的例子,但是我展示的视图控制器被包装在它自己的导航控制器中。因此,在该视图控制器中,当我需要确定是否添加关闭按钮和后退按钮时,我只需检查导航控制器堆栈大小。如果显示屏幕,堆栈大小应为1(需要关闭按钮)。。。如果使用现有的导航控制器推送,则堆栈大小将大于1(需要返回按钮)


你可以这样做,既快又安全

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
}

一个优雅的答案,我在这里没有看到:

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

信用:基于@AmitaiB answer中创建函数的

小修改

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 
}
在iOS 9(或更高版本)上的Swift中:

如前所述,这是最好的方式

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

我认为这个问题的答案可能会对你有所帮助:突然你需要两个例子,而你被搞砸了,因为你让高地人输了。斩首无助的视图控制器,惊叹“只能有一个!”isBeingPresented正是我需要检查是否确定我的视图控制器是否在iOS 5.0及更高版本中显示或推送的视图控制器。但是为了支持4.3,我不能只检查parentViewController是否为nil,对吗?。因为parentViewController不是nil,所以在这两种情况下都是push和presenting。parentViewController文档说“在iOS 5.0之前,如果视图没有父视图控制器并且正在呈现,则将返回呈现视图控制器。”此外,我不理解在运行时添加实现。可以详细说明吗?。在iOS中,如果您检查根视图控制器,则该值始终为零。对于根控制器,我检查self.presentedViewController==nil。如果它不是nil,则表示它呈现了其他内容,并且根不再可见。
if(isModallyPresented(tmpVC:myTopVC)){
//return true if viewcontroller is presented 
}
if viewController.viewIfLoaded?.window != nil {
    // viewController is visible
}
            BOOL presented = [[self.navigationController viewControllers] count] == 1;
        if (presented) {
            [self dismissViewControllerAnimated:YES completion:^{
                // do whatever you need here
            }];
        }
        else {
            [self.navigationController popViewControllerAnimated:YES];
        }