是否可以确定ViewController是否显示为Modal?

时间:2010-05-09 18:24:17

标签: iphone ios view controller modal-dialog

是否可以在ViewController类中检查它是否显示为模态视图控制器?

14 个答案:

答案 0 :(得分:95)

由于iOS 6中已弃用modalViewController,因此这是一个适用于iOS 5+的版本,可以在没有警告的情况下进行编译。

目标-C:

- (BOOL)isModal {
    return self.presentingViewController.presentedViewController == self
      || (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController)
      || [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];
}

夫特:

var isModal: Bool {
    return self.presentingViewController?.presentedViewController == self
        || (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController)
        || self.tabBarController?.presentingViewController is UITabBarController
}

给菲利普的答案提示。

答案 1 :(得分:77)

如果你正在寻找iOS 6+,这个答案已被弃用,你应该检查Gabriele Petronella's answer


作为UIKit原生的属性或方法,没有简洁的方法可以做到这一点。您可以做的是检查控制器的几个方面,以确保它以模态形式呈现。

因此,要检查当前(在下面的代码中表示为self)控制器是否以模态方式呈现,我的函数可以在{{ 1}}类别,或者(如果你的项目不需要使用其他UIKit控制器,例如UIViewController)在我的其他控制器继承的基础控制器中

UITableViewController

编辑: 我添加了最后一项检查以查看是否正在使用UITabBarController,并将另一个UITabBarController呈现为模态。

编辑2:添加了iOS 5+检查,其中-(BOOL)isModal { BOOL isModal = ((self.parentViewController && self.parentViewController.modalViewController == self) || //or if I have a navigation controller, check if its parent modal view controller is self navigation controller ( self.navigationController && self.navigationController.parentViewController && self.navigationController.parentViewController.modalViewController == self.navigationController) || //or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation [[[self tabBarController] parentViewController] isKindOfClass:[UITabBarController class]]); //iOS 5+ if (!isModal && [self respondsToSelector:@selector(presentingViewController)]) { isModal = ((self.presentingViewController && self.presentingViewController.modalViewController == self) || //or if I have a navigation controller, check if its parent modal view controller is self navigation controller (self.navigationController && self.navigationController.presentingViewController && self.navigationController.presentingViewController.modalViewController == self.navigationController) || //or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation [[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]]); } return isModal; } 不再回答UIViewController,而是改为parentViewController

编辑3:我为https://gist.github.com/3174081

创建了一个要点

答案 2 :(得分:35)

在iOS5 +中,正如您在UIViewController Class Reference中所看到的,您可以从属性“presentsViewController”中获取它。

presentingViewController 提供此视图控制器的视图控制器。 (只读)

@property(nonatomic,readonly)UIViewController * presentsViewController
讨论

如果接收此消息的视图控制器由另一个视图控制器呈现,则此属性保存呈现它的视图控制器。如果未显示视图控制器,但正在显示其中一个祖先,则此属性使视图控制器保持显示最近的祖先。如果视图控制器或其任何祖先都没有出现,则此属性为零。

可用性
适用于iOS 5.0及更高版本 声明
UIViewController.h

答案 3 :(得分:17)

如果没有,您可以在UIViewController子类中为此(presentedAsModal)定义一个属性,并在将ViewController作为模态视图呈现之前将其设置为YES

childVC.presentedAsModal = YES;
[parentVC presentModalViewController:childVC animated:YES];

您可以在viewWillAppear覆盖中检查此值。

我认为没有一个官方财产说明了如何呈现视图,但没有任何东西阻止你创建自己的视图。

答案 4 :(得分:8)

如果self.navigationController是模态呈现但是self不等于self.navigationController.viewControllers [0],则

Petronella's answer不起作用,在这种情况下会推送self。

以下是解决问题的方法。

return self.presentingViewController.presentedViewController == self
            || (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController && self == self.navigationController.viewControllers[0])
            || [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];

在斯威夫特:

return self.presentingViewController?.presentedViewController == self
        || (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController && self.navigationController?.viewControllers[0] == self)
        || self.tabBarController?.presentingViewController is UITabBarController

答案 5 :(得分:6)

这应该有效。

if(self.parentViewController.modalViewController == self)…

答案 6 :(得分:4)

检查的最佳方式

 if (self.navigationController.presentingViewController) {
         NSLog(@"Model Present");
    }

答案 7 :(得分:2)

如果您不需要区分全屏模式视图和非模态视图(我的项目中就是这种情况)(我正在处理只有表单和页面表发生的问题),您可以使用UIViewController的modalPresentationStyle属性:

switch (self.modalPresentationStyle) {
    case 0: NSLog(@"full screen, or not modal"); break;
    case 1: NSLog(@"page sheet"); break;
    case 2: NSLog(@"form sheet"); break;
}

答案 8 :(得分:2)

Swift

func isUIViewControllerPresentedAsModal() -> Bool {
    if((self.presentingViewController) != nil) {
        return true
    }

    if(self.presentingViewController?.presentedViewController == self) {
        return true
    }

    if(self.navigationController?.presentingViewController?.presentedViewController == self.navigationController) {
        return true
    }

    if((self.tabBarController?.presentingViewController?.isKindOfClass(UITabBarController)) != nil) {
        return true
    }

    return false
}

答案 9 :(得分:1)

在我的项目中,我有一个视图控制器(细节),可以通过主视图控制器以模态方式(添加新项目时)或推送(编辑现有项目时)显示。当用户点击[完成]时,详细信息视图控制器调用主视图控制器的方法以通知它已准备好关闭。 Master必须确定详细信息的呈现方式,以便知道如何关闭它。这就是我这样做的方式:

UIViewController *vc = self.navigationController.viewControllers.lastObject;
if (vc == self) {
    [self dismissViewControllerAnimated:YES completion:NULL];
} else {
    [self.navigationController popViewControllerAnimated:YES];
}

答案 10 :(得分:0)

这样的黑客可能会有用。

UIViewController* child = self;
UIViewController* parent = child.parentViewController;
while (parent && parent.modalViewController != child) {
    child = parent;
    parent = child.parentViewController;
}
if (parent) {
    // A view controller in the hierarchy was presented as a modal view controller
}

但是,我认为我以前的答案是一个更清洁的解决方案。

答案 11 :(得分:0)

对我有用的是:

// this is the trick: set parent view controller as application's window root view controller
UIApplication.sharedApplication.delegate.window.rootViewController = viewController;

// assert no modal view is presented
XCTAssertNil(viewController.presentedViewController);

// simulate button tap which shows modal view controller
[viewController.deleteButton sendActionsForControlEvents:UIControlEventTouchUpInside];

// assert that modal view controller is presented
XCTAssertEqualObjects(viewController.presentedViewController.class, MyModalViewController.class);

据我测试,这适用于iOS7和iOS8。但是没试过iOS6。

答案 12 :(得分:0)

我已经看了一下这个问题的正确答案,我找不到涵盖所有可能情景的任何内容。我写了几行代码,似乎可以完成这项工作。您可以找到一些内联注释来确定已经检查过的内容。

- (BOOL)isModal {
    BOOL modal = NO;
    if ([self presentingViewController]) { //Some view Controller is presenting the current stack
        UIViewController *presented = [[self presentingViewController] presentedViewController]; // What's been presented
        if ([presented respondsToSelector:@selector(viewControllers)]) { // There's a stack
            NSArray *viewControllers = [presented performSelector:@selector(viewControllers)];
            modal = [viewControllers firstObject] == self; // Current VC is presented modally if it's the first in the stack
        }
        else {
            modal = presented == self; // Don't think this is actually needed. set modal = YES should do the job tho.
        }
    }
    return modal;
}

希望得到这个帮助。

答案 13 :(得分:0)

这是@ GabrielePetronella的isModal的修改版本,它与包含的视图控制器一起工作,因为它首先向上移动parentViewController层次结构。还将代码拉出多行,以便清楚它正在做什么。

var isModal: Bool {
    // If we are a child view controller, we need to check our parent's presentation
    // rather than our own.  So walk up the chain until we don't see any parentViewControllers
    var potentiallyPresentedViewController : UIViewController = self
    while (potentiallyPresentedViewController.parentViewController != nil) {
        potentiallyPresentedViewController = potentiallyPresentedViewController.parentViewController!
    }

    if self.presentingViewController?.presentedViewController == potentiallyPresentedViewController {
        return true
    }

    if let navigationController = potentiallyPresentedViewController.navigationController {
        if navigationController.presentingViewController?.presentedViewController == navigationController {
            return true
        }
    }

    return potentiallyPresentedViewController.tabBarController?.presentingViewController is UITabBarController
}