ios 如何识别呈现的 UIViewController

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15090987/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 22:27:54  来源:igfitidea点击:

How to identify that an UIViewController is presented

iphoneiosobjective-cuiviewcontrollermodalviewcontroller

提问by saikamesh

I have created an UIViewController sub class which can either be pushed in a navigation stack of a UINavigationController or presented(modally) from any UIViewController. I need to identify whether my view controller is presented, if it is presented I need to add a toolbar with a close button at the top of the view controller. (else if it is pushed in navigation stack then the default close button will get added, by using that the user can go back.)

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

In all the available versions say 4.3, 5.0, till 6.0, from inside an UIViewController sub class, Can I assume that the view controller is presented(modally) if the following condition is satisfied.

在所有可用版本中,从 UIViewController 子类内部的 4.3、5.0 到 6.0,如果满足以下条件,我是否可以假设视图控制器(模态)呈现。

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

回答by danyowdee

With iOS 5, UIViewController gained a readonly property named presentingViewController, that replaces the older semantics of parentViewController(which now describes containment). This property can be used when a view controller needs to get at the view controller that's presenting it — note: this will often be something else than what you'd expect, if you're new to the API!

在 iOS 5 中, UIViewController 获得了一个名为 的只读属性presentingViewController,它取代了旧的语义parentViewController(现在描述的是contains)。当视图控制器需要访问呈现它的视图控制器时,可以使用此属性 - 注意:如果您不熟悉 API,这通常与您期望的不同!

In addition, the isBeingPresentedproperty had been introduced to pretty much solve the class of situations you're currently in. Check for this property in your view controller's viewWillAppear:.

此外,isBeingPresented引入该属性几乎可以解决您当前所处的情况。在您的视图控制器的viewWillAppear:.

Update

更新

I overread that you seem to target iOS 4.3 as well:
In that case, you need to guard the call to isBeingPresentedwith an if ([self respondsToSelector:…])you can then in the elseblock check for whether the parentViewController is not nil.

我读到你似乎也以 iOS 4.3 为目标:
在这种情况下,你需要isBeingPresented用一个来保护调用,if ([self respondsToSelector:…])然后你可以在else块中检查 parentViewController 是否不为零。

Another approach to backwards compatibility might be to override +resolveInstanceMethod:to add an implementation for -isBeingPresentedat runtime. This will leave your calling sites clean, and you'd get rid of runtime-magic as soon as you let go of ancient iOS support ;-)

另一种向后兼容的方法可能是覆盖+resolveInstanceMethod:-isBeingPresented在运行时添加实现。这将使您的调用站点保持干净,并且一旦您放弃古老的 iOS 支持,您就会摆脱运行时魔法;-)

Note, though, that there are edge cases to this, and you initial approach as well, when running on iOS <5:

但是请注意,在 iOS <5 上运行时,这有一些边缘情况,您也可以采用初始方法:

The view controller can be presented contained in any other view controller—including navigation controllers. When that last case happens, you're out of luck: parentViewControllerwill be nil, while navigationControllerwill not. You can try to add gobs of unwieldy code to mitigate this limitation in older iOSes…or you could just let it go.

视图控制器可以包含在任何其他视图控制器中——包括导航控制器。当最后一种情况发生时,你就不走运了:parentViewControllerwill be nil,而navigationControllerwill not。您可以尝试添加大量笨拙的代码来减轻旧 iOS 中的这种限制……或者您可以放手。

回答by Evelyn Loo

I use the this code to check whether the UIViewController is presented.

我使用此代码来检查 UIViewController 是否存在。

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

回答by Martin M Reed

I had a similar case, however the view controller that I presented is wrapped in it's own navigation controller. So in that view controller when I need to determine whether or not to add the close button vs a back button, I just check the navigation controllers stack size. If the screen is presented, the stack size should be one (needs close button)... and if it is pushed using an existing navigation controller, then stack size will be larger than one (needs back button).

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

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

回答by Gl0ub1l

To handle this kind of behavior, I usually set/reset a BOOL toggling it in viewWillAppear/viewWillDisappear methods.

为了处理这种行为,我通常在 viewWillAppear/viewWillDisappear 方法中设置/重置一个 BOOL 来切换它。

By the way, your test condition seems incorrect. I think you should use

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

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

Why can't you just always add the toolbar to your view controller? Is there any case the view is loaded but never presented?

为什么不能总是将工具栏添加到视图控制器中?是否存在视图已加载但从未呈现的情况?

回答by Jason Lee

@saikamesh.

@赛卡梅什。

As you use UINavigationController to navigate your viewControllers, I think you can use topViewController(Doc here) and visibleViewController(Doc again) to reach your intention.

当您使用 UINavigationController 导航您的 viewController 时,我认为您可以使用topViewController此处为 Doc)和visibleViewController再次Doc)来达到您的意图。

You mention that :

你提到:

when it is pushed in navigation stack then the default close button will get added, by using that the user can go back

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

If the instance of the the specific UIViewController is important, I think it better to create a shared singleton instance and provide a global presented flag:

如果特定 UIViewController 的实例很重要,我认为最好创建一个共享单例实例并提供一个全局呈现标志:

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

and to check if it is presented:

并检查它是否出现:

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

Or, you can read the much accepted answer.

或者,您可以阅读广为接受的答案

:) Hope helps.

:) 希望有所帮助。

回答by Ali A. Jalil

In Swift on iOS 9 (or later):

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

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

回答by Banker Mittal

Please check this way:

请检查这种方式:

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

    }
}

回答by Alejandro Luengo

You could do it like this, it's fast and safe

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

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
}

回答by AmitaiB

One elegant answer that I haven't seen 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
    }
}

credit: based on this gist

信用:基于这个要点

回答by Vlad

You can at any point check whether you have a modal view controller presented or not by using the modalViewController property from your navigation controller. Ex:

您可以随时使用导航控制器中的 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
      }
   }