【问题标题】:How to Dismiss 2 Modal View Controllers in Succession?如何连续关闭 2 个模态视图控制器?
【发布时间】:2011-03-14 13:14:41
【问题描述】:

我有 2 个以模态方式呈现的视图控制器。

A presents B which presents C.

当我解雇 C 时,我也想解雇 B。但我不知道该怎么做:

解雇 C:

[self dismissModalViewControllerAnimated:YES]
//[delegate dismissB] //this doesn't work either when i create a delegate pattern

现在我只剩下 B 了。我怎样才能从 C 中解雇 B?

【问题讨论】:

    标签: iphone objective-c cocoa-touch uikit uiviewcontroller


    【解决方案1】:

    刚刚发现需要在 iOS 5 中使用 presentingViewController。

    [self.presentingViewController.presentingViewController dismissModalViewControllerAnimated:YES];
    

    A -> B -> C

    在模态C中运行上述代码将带你回到A

    【讨论】:

    • 没问题 :-) 我遇到的每个示例都是针对 iOS5 之前的并且从未工作过
    • 使用委托将视图控制器从presentingViewController中解散是正确的。 (根据 Apple 指南)
    • ...dismissModalViewControllerAnimated 现在已弃用。试试[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
    • 这适用于 ios7,但在 ios8 中,如果 B 显示为 modalPresentationStyle OverCurrentContext,您必须调用 [A dismissController] 两次
    • 对我不起作用,因为我在控制器 C 的解除方法的完成块中拥有它......当然意识到它不起作用,self 为零!大声笑
    【解决方案2】:

    这对我有用,非常简单

    // Call inside View controller C    
    self.presentingViewController?.dismissViewControllerAnimated(false, completion: nil)
    self.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
    

    解释:

    如果你在 C 上调用dismiss,它只能移除 C。如果你在 B 上调用dismiss,它会做正确的事:移除最顶层的模态视图控制器。因此,第一次调用删除了 C(没有动画)。第二次调用删除 B。

    从 C 访问视图控制器 B 的最简单方法是使用 presentingViewController 变量。

    【讨论】:

      【解决方案3】:

      在 B. 放:

      [self dismissModalViewControllerAnimated:NO];
      [self dismissModalViewControllerAnimated:YES];
      

      只运行一个动画。

      【讨论】:

      • 对于 Swift 5,我使用它并且它有效:self.presentingViewController?.dismiss(animated: false) self.presentingViewController?.dismiss(animated: true)
      【解决方案4】:

      在 Swift 4 中

      self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil);

      【讨论】:

        【解决方案5】:

        尝试使用 B 中的下一个代码(在关闭 C 之后,就像你已经做的那样):

        [self.parentViewController dismissModalViewControllerAnimated:YES];
        

        重要提示
        请勿在此行之后的方法中执行任何操作。
        这个视图控制器(B)可能会被释放和释放......

        更新
        从 iOS7 开始,不推荐使用上述方法。
        请改用下一种方法:

        [self.parentViewController dismissViewControllerAnimated:YES completion:^{ /* do something when the animation is completed */ }];
        

        【讨论】:

        • 我试过了,但它只是简单地忽略了 C。B 仍然可见。
        • 尝试在没有动画的情况下关闭 C,然后用动画关闭 B...顺便说一句,这个关闭代码在哪里(哪个类以及这个方法是如何调用的)?
        • Dismissing 代码位于 C 中一个名为 dismissAll 的方法中。它是通过按下 UIBarButtonItem 触发的。
        • 当我写下我的答案时,我确信它位于 B 中...... 关闭模态视图控制器的常见解决方案是调用委托中的方法(打开模态视图的视图控制器)和在该方法中,模式视图控制器应该被解除。在您的情况下,A 应该是 B 的代表,B 应该是 C 的代表;在 C 中,您应该在 B 中调用一个应该关闭 C 的委托方法并在 A 中调用一个应该关闭 B 的委托方法......我希望现在已经足够清楚了。
        • 此方法在 iOS 7/8 中已弃用 — 应该取而代之的是什么?
        【解决方案6】:

        快速检查一下:

        self.presentingViewController?.presentingViewController?.dismissViewControllerAnimated(true, completion: nil);
        

        【讨论】:

          【解决方案7】:

          我阅读了所有主题,但没有找到正确的答案。如果您解雇 B,那么 C 将立即消失并产生奇怪的效果。正确的方法是将 C 呈现为具有自定义动画的子视图控制器,例如:

             [b addChildViewController:c];
              c.view.frame = CGRectOffset(b.view.bounds, 0, b.view.bounds.size.height);
              [b.view addSubview:c.view];
              [c didMoveToParentViewController:b];
          
              [UIView animateWithDuration:0.5 animations:^{
                  c.view.frame = CGRectOffset(c.view.frame, 0, -b.view.bounds.size.height);
              } completion:^(BOOL finished) {
          
              }];
          

          然后你简单地解雇 B,它看起来好多了!

          【讨论】:

            【解决方案8】:

            这对我有用:

            // Swift
            presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
            
            // Objective-C
            [self.presentingViewController dismissViewControllerAnimated:true completion:nil];
            

            【讨论】:

            • Objective-C 中的消息传递参数不是用逗号分隔的,所以在“true”之后将没有逗号为 // Objective-C [self.presentingViewController dismissViewControllerAnimated: true completion: nil]
            • B 在我添加您的代码时不会被解雇,请同时更新您的目标 c 语法。去掉 true 后的逗号。
            【解决方案9】:

            您只需要一个解除命令。只需解雇 B,然后 C 就会消失。

            【讨论】:

            • 这种方法似乎效果很好。有人认为这种方法有什么缺点吗?
            【解决方案10】:

            导航控制器有一个“viewControllers”属性,它是一个数组 - 您可以将其设置为一个新数组,减去要删除的两个视图控制器。

            【讨论】:

              【解决方案11】:

              受 Albertos 解决方案的启发,我在 B 中创建了一个委托方法,其中包含一个块来显示删除帐户的结果:

              #pragma - mark - AddAccountViewControllerDelegate Methods
              
              - (void) dismissToSettings {
                  [self dismissModalViewControllerAnimated:NO];
                  [self dismissViewControllerAnimated:YES completion:^(void){[DKMessage showMessage:LS(@"Account was successfully created")];}];
              }
              

              【讨论】:

                【解决方案12】:

                我遇到了同样的问题,更好的解决方案是创建一个“DismissViewProtocol”,如下所示:

                文件:DismissViewProtocol.h

                @protocol DismissViewProtocol <NSObject>
                -(void)dismissView:(id)sender;
                @end
                

                在我的 B-modal 视图中,让我们响应委托方法:

                在我的 b.h 文件中:

                #import "DismissViewProtocol.h"
                @interface B-Modal : UIViewController <DismissViewProtocol>
                ...
                @end
                

                在我的 b.m 文件中:

                -(void) dismissView:(id)sender
                {
                 [((UIViewController *) sender) dismissModalViewControllerAnimated:NO];
                 [self dismissModalViewControllerAnimated:YES];
                }
                

                在同一个 B 视图控制器中,当我调用 接下来,在我的 B 模态视图中,当我调用另一个模态视图 C 时,假设为 segue:

                -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
                {
                    ((C-ViewController *)segue.destinationViewController).viewDelegate=self;
                }
                

                最后,在我的 c.h 文件中,让我们为委托做准备:

                @property(nonatomic, weak) id <DismissViewProtocol> viewDelegate;
                

                在我的 c.m 文件中,我只是告诉我的 viewDelegate 关闭我的模态视图控制器及其本身:

                -(void)closeBothViewControls
                {
                       [self.viewDelegate dismissView:self];
                }
                

                就是这样。

                希望对大家有用。

                【讨论】:

                  【解决方案13】:

                  这是一种如何使用重复循环关闭多个模式视图控制器的方法:

                  斯威夫特 3

                  // In this example code will go throw all presenting view controllers and 
                  // when finds it then dismisses all modals.
                  var splitViewController: UIViewController? = self
                  
                  repeat {
                      splitViewController = splitViewController?.presentingViewController
                  } while (!(splitViewController is UISplitViewController) && (splitViewController != nil))
                  
                  splitViewController?.dismiss(animated: true, completion: nil)
                  

                  【讨论】:

                    【解决方案14】:

                    我知道这个答案可能会让人觉得多余,但下面的陈述应该是有道理的 然后你就会知道它是如何工作的。

                    只需关闭最旧的视图控制器,所有其他后来的视图控制器都会随之消失。

                    如果有 2 个视图控制器:

                    目标 C:

                    [self.presentingViewController dismissViewControllerAnimated:true completion:nil]
                    

                    斯威夫特:

                    presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
                    

                    【讨论】:

                      【解决方案15】:

                      我找到了解决方案。

                      您可以将这些 ViewControllers 放入单个 NavigationController 中。而不是解雇NavigationController 将导致所有这些ViewControllers 立即解雇。

                      https://gist.github.com/ufo22940268/2949fdf59c9860292f263ebb1e8036d7

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-06-24
                        • 2013-01-01
                        相关资源
                        最近更新 更多