解决多个模态视图控制器无法关闭的问题

14

我在使用模态视图控制器时遇到了问题。 我有一个父视图控制器,它是模态视图A的代理。在模态视图A中,我展示了模态视图B,并通过委托使模态视图A消失。

当模态视图B出现时,屏幕会变暗并且界面无法操作,但应用程序不会崩溃。我将动画设置为“NO”,但仍然出现相同的问题。

事件顺序:

  1. 父视图显示模态视图A
  2. 模态视图A在模态视图A控制器中展示模态视图B
  3. 父视图通过委托在模态视图A控制器中解除模态视图A
  4. 这就是我的界面挂起的地方,我可以看到模态视图B但无法点击或执行任何操作
9个回答

19
你可以使用这个。
[[[self presentingViewController] presentingViewController]  dismissModalViewControllerAnimated:YES];

4
有没有方法在解除时不显示中间视图控制器?例如,A呈现B,B再呈现C。从C开始,使用self.presentingViewController.presentingViewController.dismissViewController(),但是在过渡期间会出现B闪烁的情况。我宁愿只让C向下滑动并出现A。编辑:看起来这只是iOS 8以后的一个错误 :( - dfickling
@dfickling,你有没有解决那个问题的方案? - Mohammad Zaid Pathan

4

通过让我的parentViewController作为代理,问题得到了解决。以下是我的步骤:

[parentView presentViewController:modalViewControllerA animated:YES]
[parentView dismissModalViewControllerAnimated:YES]
[parentView presentViewController:modalViewControllerB animated:YES]
//Modal B dismisses himself

在我的代理方法中,我需要确保在展示模态框B之前关闭模态框A。

4
一个模态视图控制器必须要有一个父视图控制器才能显示。如果你关闭了父视图控制器(在你这种情况下是“模态视图A”),那么行为将是不可预测的。
如果你确定嵌套模态视图控制器是你真正想要的,那么你需要按相反的顺序关闭它们;等到你完成了“B”,然后关闭“B”,再关闭“A”。
如果你不需要模态呈现样式,最好使用UINavigationController来维护你的视图控制器堆栈。
更新:以下是我重新排列事件顺序的方式。为了清晰起见,以代码形式呈现。
  1. [parentView presentViewController:modalViewControllerA animated:YES]
  2. [modalViewControllerA presentViewController:modalViewControllerB animated:YES]
  3. [modalViewControllerA dismissModalViewControllerAnimated:YES]
  4. [parentView dismissModalViewControllerAnimated:YES]

我修改了我的问题,并展示了我的事件顺序。我按相反的顺序解除它们。 - Sheehan Alam
在第三步之前,我没有解除 Modal View B。我在 Modal View B 中有一个取消和完成按钮,它将自行解除。我希望我可以解除 Modal View A,在 Modal View B 中进行一些工作,然后自行解除。 - Sheehan Alam
在我的代码中,parentView 实现了 Modal View A 的委托协议(dismissModal)。如果我在 Modal View A 中,并调用 Modal View B,那么我应该在哪里关闭 Modal View A? - Sheehan Alam
有趣的是,当我让我的委托处理呈现模态视图A和模态视图B时,我会得到奇怪的错误。父视图无法显示模态视图B,但可以解除模态视图A。 - Sheehan Alam
太棒了!我一直在模态视图控制器中使用[self dismissModalViewController...],直到我嵌套它们。幸运的是,我需要一个指向父视图控制器的本地属性指针,所以现在我使用[parentViewController dismiss...],这解决了嵌套问题!谢谢。 - Jay Imerman
显示剩余8条评论

1

适用于 iOS 6+- presentViewController:animated:completion:

[[[self presentingViewController] presentingViewController]  dismissViewControllerAnimated:YES completion:nil];

1

in Swift 2.1

you can try

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

对我有效

视图A -> 视图B -> 视图C

将此代码应用于视图C,您将会回到视图A


0

简单:

关闭所有视图:

[self dismissModalViewController animated:YES];
[self dismissModalViewController animated:YES];
[self dismissModalViewController animated:YES];
[self dismissModalViewController animated:YES];

(每添加一个模态视图)

然后呈现一个新的模态视图控制器


通过这个解决方案,下降顺序中的ModalViewControllers如何知道上面的视图已经被dismissed? - Rik Smith-Unna

0

可能经过很长时间,但是我遇到了同样的问题,这是唯一一个有答案的帖子。

我不明白您所说的将parentViewController的代理设置为self是不允许的意思。

目前我正在做的是

[self presentModalViewController:ViewControllerA animated:YES];
[self dismissModalViewControllerAnimated:YES];// inside ViewControllerA
[self presentModalViewController:ViewControllerB animated:YES];
[self dismissModalViewControllerAnimated:YES];// inside ViewControllerB

问题是在视图控制器A之后,视图控制器B的视图没有呈现。

谢谢。


0

我有一个主视图,需要显示一个模态视图1,在其中一个按钮呈现了模态视图2。看起来你也需要这样做。 但是在模态视图2中有一个按钮可以返回到主视图。

所以解决方案是: 主视图呈现UINavigationController,其根控制器为模态视图1。然后通过"[self.navigationController modalview2 animated:YES];"呈现模态视图2。

当模态视图2需要返回到主视图时,只需使用"[self.parentViewController dismissModalViewControllerAnimated:YES];",即可隐藏UINavigationController。

希望这很清楚。


0

关于dismiss(animated:completion:)方法的苹果文档。

在“讨论”部分中,它说:

any intermediate view controllers are simply removed from the stack.

如果您按顺序呈现多个视图控制器,从而构建一个呈现的视图控制器堆栈,则在堆栈较低的视图控制器上调用此方法会关闭其直接子视图控制器和该子视图控制器之上的所有视图控制器。当发生这种情况时,只有最顶部的视图以动画方式消失;任何中间视图控制器都将从堆栈中简单地移除。最顶部的视图使用其模态转换样式进行解除,该样式可能与堆栈中较低的其他视图控制器使用的样式不同。
换句话说,如果视图控制器堆栈如下所示:
Root -> A -> B -> C -> D ... -> Z

D 调用 dismiss 方法后,所有在 D 后面的视图控制器,例如: (E ... Z),将会从堆栈中移除。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接