关于iOS 14导航堆栈管理的问题(与iOS 13不同)

关于iOS 14导航堆栈管理的问题(与iOS 13不同),ios,uikit,Ios,Uikit,我一直在iOS上测试我们的应用程序,我注意到iOS 14上出现了一种奇怪的行为,但iOS 13上没有。这是关于导航堆栈及其工作方式的 假设我有一个[a,B,C]的导航堆栈,其中C当然是最顶层的视图控制器。我在C视图控制器中有一个按钮,它获取导航堆栈,删除C,然后删除B,最后添加一个新的视图控制器D。然后我将新堆栈设置为导航控制器 在iOS 13上,生成的堆栈是[A,D]。 在iOS 14上,生成的堆栈是[C,A,D]。不知何故,它不允许我从堆栈中删除当前视图控制器,但它确实添加到了堆栈的底部 我

我一直在iOS上测试我们的应用程序,我注意到iOS 14上出现了一种奇怪的行为,但iOS 13上没有。这是关于导航堆栈及其工作方式的

假设我有一个[a,B,C]的导航堆栈,其中C当然是最顶层的视图控制器。我在C视图控制器中有一个按钮,它获取导航堆栈,删除C,然后删除B,最后添加一个新的视图控制器D。然后我将新堆栈设置为导航控制器

在iOS 13上,生成的堆栈是[A,D]。 在iOS 14上,生成的堆栈是[C,A,D]。不知何故,它不允许我从堆栈中删除当前视图控制器,但它确实添加到了堆栈的底部

我唯一的解释是,它与iOS 14中新的导航历史功能(长时间按住后退按钮)有关。不知何故,这在导航堆栈的管理上引入了一些新的约束


希望有人能帮助我理解新的行为。

我在最新的iOS 14中也面临类似的问题-如果我在
UINavigationController
上使用
setViewControllers:animated:
,而不是将导航堆栈完全替换为作为参数提供的视图控制器数组,它保留当前最顶部的视图控制器,并将新的视图控制器推到其顶部

基本上,如果当前视图控制器堆栈为:

[V1, V2, V3,... Vn]
使用参数为的
setViewControllers:animated

[X1, X2, X3,... Xn]
转换后,视图控制器堆栈将:

[Vn, X1, X2, X3,... Xn]

此错误不会发生在iOS 13及更低版本上。

这似乎确实是早期的测试版问题,并已在iOS 14 beta 6/Xcode 12 beta 6中修复

let navigationController=UINavigationController(rootViewController:originalViewController)
navigationController.SetViewController([replacementViewController],动画:true)
调用
setViewControllers

navigationController.ViewController

现在产生预期结果
[replacementViewController]
(与iOS 13行为匹配)。

我找到了解决此问题的简单方法。如果要使用SetViewController设置新的VC数组,请首先使用空数组调用SetViewController(UIViewController),然后立即使用实际数组再次调用SetViewController


需要注意的是,将调用willShow navigationController委托,并且它的viewController参数将被统一化。因此,您可以首先检查viewControllers.count是否为0,如果为0,则退出将显示。

我也遇到过此类问题。在我的例子中,我得到了一个导航控制器,它的堆栈上只有一个视图控制器,比如说
[viewControllerA]
。在进行以下工作时:

navigationController.setViewController([viewControllerB], animated: true)
在iOS 14上,导航堆栈变为:

[viewControllerA, viewControllerB]
在iOS 13(及以下版本)上,它变成:

[viewControllerB]
正如@Sanzio Angeli在上面提到的,这是由使用
true
on
animated
参数调用
setViewControllers
时的不同行为引起的

这种行为并非微不足道,尽管在上有详细描述,但如果您查看其来源,您可以阅读以下评论:

打开func setViewController(ViewController:[UIViewController],animated:Bool)/如果animated为YES,则根据新的俯视图控制器以前是否在堆栈中模拟推送或弹出。

解决方案

a) 将
animated
参数设置为
false
,调用:

navigationController.setViewController([viewControllerB], animated: false)

b) 只需以这种方式设置
viewControllers
(与前面的调用相同):


尽管我无法评论行为的具体工作方式,但请尝试使用popToViewController之类的函数,而不是使用SetViewController之类的函数专门重置整个堆栈。这会改变什么吗?我很感兴趣。iOS 14也在测试阶段,所以我想还是有一些问题。@SanzioAngeli你好,Sanzio。令人惊讶的是,使用popToViewController似乎确实完成了它的工作。回到我的示例,使用viewController A作为参数的popToViewController,我得到的是[A],而不是我使用SetViewController时得到的[C,A]。我认为这指向了一个bug,因为这两种方法在iOS13中的工作原理相同,但正如您所说,IOS14仍处于测试阶段。非常感谢你的想法:D。有趣。你应该填些东西,但我不知道怎么做。你应该立即提交一份错误报告。苹果将很快推出iOS 14的最终版本!其他人在这里也经历过这样的情况:我在这里共享了这个SO链接,我在beta 7上仍然存在问题:/n无论我使用setViewControllers、popToRootViewContoller还是PopViewControllers,当设置动画时,结果总是一样的:堆栈混淆了。问题仍然存在于版本12.1(12A7403)(公共)。下面是我所做的:在设置视图控制器之前,尝试在没有动画的情况下设置空数组[]在我的情况下,这很有帮助!navigationController.SetViewController([],动画:false)navigationController.SetViewController([replacementViewController],动画:true)在更新Xcode 12 GM发布版本后,我在现有项目中面临同样的问题。您在Xcode 12中有解决此问题的方法吗?@MiguelA。这个问题在Xcode 12 beta 7中得到了解决,此后我就再也没有见过它。你确定你在通用汽车上看到了这一点吗?当然,我安装了Xcode 12 GM版本,我看到了这个问题,所以我一起安装了Xcode 12 GM和11.7。临时am building应用程序由11.7版本解决it@MiguelA. 据我所知,如果在ViewDid出现之前检查堆栈,仍然会发生这种情况。不管怎么说,看起来不错。我真的很想找到一个解决办法,使它在viewDidLoad上也能工作。。
navigationController.viewControllers = [viewControllerB]