关闭模态视图控制器堆栈

7

给定以下视图控制器布局。

View Controller Layout

我们通过首先在A上呈现B,然后在B上呈现C来构建模态视图控制器堆栈。根据苹果关于dismiss(animated:completion:)的文档,在A上调用它实际上应该以动画方式解除顶部视图控制器(在这种情况下为C)和所有中间视图控制器,但发生的是C被无动画地解除,而B则以动画方式解除。
我上传了一个Xcode项目到GitHub,复制了这个行为。我是不是漏掉了什么或者我误解了这里的文档?

你解决了吗?我也遇到了同样的问题,感到非常沮丧。这个问题似乎存在于多个版本的iOS中,并且在iOS 10中仍然存在。这与文档中记录的行为(和常识)直接相反,应该对最上层的视图控制器进行动画处理,而不是中间的那些。 - MobileVet
不,我仍然遇到了这个问题。也许现在是时候提交一个雷达报告了... - mAu
刚刚找到了一个问题...它被复制了一遍,然后因为长时间没有活动而被关闭了。还发现了一个测试项目,可以快速演示这个问题。苹果公司认为他们在8.3版本中解决了这个问题,但用户从未更新过,所以他们关闭了这个错误...但它仍然存在,今天仍然存在。 - MobileVet
我刚向苹果提交了一个编号为#28713792的错误报告。我附上了另外一位好心人创建的测试项目,希望能够容易理解。 - MobileVet
会复制的。感谢您的努力! - mAu
3个回答

7

在浏览网络并尝试各种“解决方案”后,显然这是iOS中的一个实际错误。自iOS 8以来一直存在......并且在iOS 10中仍然存在。它最初是在iOS 8中报告的,但解决方案从未得到验证,由于不活动而被苹果自动关闭了radar。

我已经提交了一个新的radar,因为这与dismissViewController的文档直接矛盾。

如果您连续呈现多个视图控制器,从而构建了一个呈现的视图控制器堆栈,则在堆栈较低的视图控制器上调用此方法(即- [UIViewController dismissViewControllerAnimated:completion])将取消显示其直接子视图控制器和该子视图控制器以上的所有视图控制器。当发生这种情况时,只有最顶部的视图以动画方式消失;任何中间视图控制器都将从堆栈中简单地删除。

清晰地展示了问题,包括预期和实际结果。感谢Boris Survorov提供测试项目和可视化效果。

预期结果实际结果iOS 8+


1
作为最新的消息,这个问题已经被安排在iOS 11.x中解决,但仍未修复。 - MobileVet
刚刚在 iOS 12 上下载并运行了测试项目,但是还是有问题。 - MobileVet
1
仍然在iOS 13上出现故障。 - Rog
1
我从苹果内部的一些人那里听说过...如果这不是一个回归错误,那么它就不会被处理。虽然很糟糕,但这解释了为什么这个问题未被修复多年。 - MobileVet

4
我曾经遇到过同样的问题,以下是我发现可行的解决方法。当你需要关闭整个堆栈时,在 A 中执行以下代码:
viewControllerB.view.isHidden = true
viewControllerC.dismiss(animated: true) // or viewControllerB.dismiss(animated:true) - it should produce the same result: dismiss viewControllerC
dismiss(animated: false) // dismisses viewControllerB

这应该会产生预期的行为。

@stanić 好的建议...如果你有很多VC堆叠在一起,它会变得有点繁琐...但确实能完成工作。 - MobileVet
@stanić,在iOS 10中,这个对你有效吗?在动画进行过程中,我得到了顶部控制器后面的黑屏。 - Mike Bernardo
@MikeBernardo 是的,对我来说它在iOS 10和iOS 11上运行正常。如果没有更多细节,很难确定你的情况可能出了什么问题。我建议您提出一个单独的问题。 - Srđan Stanić
@SrđanStanić 谢谢,我会开一个新的问题。同时,我很想知道是否有人能够使用此示例进行复制:https://github.com/mikebernardo2000/ModalDismissTest - Mike Bernardo
1
好的,我已经解决了。缺失的部分就是你需要将viewControllerB的modalPresentationStyle设为“custom”。如果不这样做,就会出现像我上面提到的黑屏问题。 - Mike Bernardo
@MikeBernardo,很高兴你解决了它! - Srđan Stanić

0

我猜你从A到B的segue也是模态的?在这种情况下,从A调用的dismiss函数想要关闭视图,该视图立即位于A之上,即B。C只是被隐藏了,以显示B的动画隐藏。在这个意义上,如果你走得那么远,你不能通过模态segue堆叠视图并使用dismiss函数来关闭顶部视图,就像你描述的那样。但是,如果从B调用dismiss来关闭C,则会按预期工作。


尽管这可能可以理解,但文档规定的预期行为并非如此。 - MobileVet
2
@MobileVet 谢谢!我不知道这在文档中有说明。我还看到你已经向苹果提交了一个错误报告。让我们看看会发生什么。说实话,我也希望那个堆栈能够正常工作,因为它可以是一个非常有用的东西。 - tech4242

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