【问题标题】:Determining if a UIViewController is being presented modally确定 UIViewController 是否以模态方式呈现
【发布时间】:2010-12-04 21:32:29
【问题描述】:

我的应用程序的主窗口包含一个基于 xib 的 UITabBarController(在 Interface Builder 中完全配置),它也可以模态显示(很像 Music.app “将歌曲添加到播放列表”模态视图)。 UITabBarController 包含许多 UINavigationControllers,这些 UINavigationControllers 又包含子类 UITableViewControllers。这就是我当前检测子类 UITableViewController 是否正在模态 UITabBarController 中呈现的方式:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.isModal = NO;

    UIViewController *child     = self;
    UIViewController *parent    = self.parentViewController;
    while (parent) {
        if (parent.modalViewController && parent.modalViewController == child) {
            self.isModal = YES;
            break;
        }
        child   = parent;
        parent  = parent.parentViewController;
    }

    if (self.isModal) {
        // modal additions, eg. Done button, navigationItem.prompt
    }
    else {
        // normal additions, eg. Now Playing button
    }
}

有没有办法做到这一点,不涉及在 parentViewController 树或子类化所有中间视图控制器以在初始化时传递 isModal 状态?

【问题讨论】:

    标签: objective-c ios


    【解决方案1】:

    如果您正在寻找 iOS 6+,此答案已弃用,您应该查看Gabriele Petronella's answer


    我前段时间回答了一个非常相似的问题,我有一个函数可以确定当前控制器是否显示为模态,而无需在此处对标签栏控制器进行子类化:

    Is it possible to determine whether ViewController is presented as Modal?

    在原始答案中,有一些关于此功能如何工作的基本解释,如果需要,您可以在那里查看,但这里是

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

    【讨论】:

      【解决方案2】:

      从 iOS5 开始,您还可以在 viewController 实例上使用 isBeingPresented

      - (BOOL)isModalViewController
      {
          return [self isBeingPresented];
      }
      

      【讨论】:

        【解决方案3】:

        Got an answer on Twitter。我最终继承了UITabBarController 并添加了一个 BOOL isModal 实例属性,该属性在模态呈现时设置为 YES。然后子视图可以使用 self.tabBarController 与子类的转换来访问 isModal 属性并相应地呈现/行为。

        【讨论】:

        • 转换为子类。这似乎很尴尬。为什么是子类?为什么不向 UITabBarController 添加一个包含 isModal 的类别?
        【解决方案4】:

        我会考虑获取根视图控制器并检查它是否具有模态视图控制器。您可以从 UIWindow 获取该视图控制器。另请注意,您可以使用 UINavigationController 的 viewControllers 属性遍历当前视图控制器的层次结构:for (UIViewController *viewController in self.navigationController.viewControllers) { ... } 更快更简单。

        【讨论】:

        • 我不明白这两个建议如何与我的问题联系起来(不是说他们没有,我只是不明白)。如果 UIWindow > UITabBarController > UINavigationBarController > ACustomTableViewController 中的按钮以模态方式呈现相同的 UITabBarController 层次结构,那么 UIWindow 中的根 UITabBarController 控制器如何知道发生了什么?关于 self.navigationController.viewControllers 不只是包含当前导航控制器中的层次结构吗?在呈现同一 UITabBarController 的单独实例的模态视图中,这对我有何帮助?
        • 当你加载你的UITabBarController时,如果它是当前UIWindow的rootViewController,你不要把Done按钮放在UI中。否则,它将在 rootViewController 之上(可能是模态的,但您应该检查以确保。)您正在考虑当前视图层次结构......
        • 另一个关于迭代视图控制器的评论只是为了告诉你你不需要检查父级等。它对知道你是否是模态的问题没有帮助.
        【解决方案5】:

        您可以在呈现视图时在自定义初始化程序中设置显示状态。我的意思是呈现它的代码会知道它是如何呈现的,对吧?

        - (void)initInModalMode:(BOOL)isModal
        

        这比让视图稍后追溯发现其状态要好?

        【讨论】:

        • 它知道它正在呈现一个 UITabBarController 但它不知道它正在呈现子类 UITableViewController(由 UITabBarController 呈现的许多中间 UINavigationController 之一呈现)实际上需要知道它是否是是否以模态方式呈现。这种方法是否不需要我对所有其他库存的中间视图控制器进行子类化以确保 isModal 值到达必要的视图?
        【解决方案6】:

        在这些 Swift 时代,有一种更简单的方法。

        extension UIViewController {
        
            var isPresentedModally: Bool {
                return presentingViewController?.presentedViewController == self || parent?.isPresentedModally == true
            }
        
        }
        

        【讨论】:

          猜你喜欢
          • 2014-05-29
          • 1970-01-01
          • 2011-11-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-09
          • 1970-01-01
          • 2015-12-28
          相关资源
          最近更新 更多