弹出到 NavigationController 堆栈中的特定 ViewController

Posted

技术标签:

【中文标题】弹出到 NavigationController 堆栈中的特定 ViewController【英文标题】:Popping to specific ViewController in NavigationController stack 【发布时间】:2019-12-04 06:14:05 【问题描述】:

我已经在我的 SceneDelegate 中以编程方式设置了 NavigationController。我的应用程序逻辑需要在某个阶段返回到堆栈上的特定 ViewController。问题是当我使用popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? 执行此操作时,我似乎失去了对 NavigationController 的跟踪——即使我没有弹回根控制器,也没有可用的后退按钮。

当我在有问题的 ViewController 中时,我的 NavigationController 的 ViewControllers 堆栈如下所示:

(lldb) po navigationController?.viewControllers
▿ Optional<Array<UIViewController>>
  ▿ some : 4 elements
    ▿ 0 : <Vocabulary.MainViewController: 0x7fbd4570dcd0>
    ▿ 1 : <Vocabulary.VocabularyViewController: 0x7fbd4566ce80>
    ▿ 2 : <Vocabulary.LearnViewController: 0x7fbd45532180>
    ▿ 3 : <Vocabulary.LearnResultViewController: 0x7fbd4569f900>

(lldb) po mainNavigationController.viewControllers
▿ 4 elements
  ▿ 0 : <Vocabulary.MainViewController: 0x7fbd4570dcd0>
  ▿ 1 : <Vocabulary.VocabularyViewController: 0x7fbd4566ce80>
  ▿ 2 : <Vocabulary.LearnViewController: 0x7fbd45532180>
  ▿ 3 : <Vocabulary.LearnResultViewController: 0x7fbd4569f900>

我现在像这样在LearnResultViewController 中弹回navigationController.viewControllers[1]

override func willMove(toParent parent: UIViewController?) 
        if let _ =  mainNavigationController.topViewController?.isKind(of: LearnResultViewController.self) 
            if isPresenting 
                if let vocabularyViewController = mainNavigationController.viewControllers.first(where:  $0 is VocabularyViewController ) 
                    mainNavigationController.popToViewController(vocabularyViewController, animated: true)
                    //navigationController?.popToViewController(vocabularyViewController, animated: true) //same behavior
                
            
        
    

isPresenting 只是我在viewDidLoad 中的LearnViewController 中设置的标志,因为在输入LearnViewController 时已经调用willMove,显然我只想在离开时弹出,mainNavigationController 是一个全局变量对现在(主要是因为我认为它应该是全局的,以便可以从到目前为止没有帮助的任何地方引用它......)。

现在,当我按下返回按钮时,我可以返回到VocabularyViewController,但那里不再有返回按钮 - 所以我的 NavigationController 的堆栈似乎丢失了。强>

虽然仍在willMove 中,但我可以看到LearnResultViewController.navigationController 变为nil - 这导致了我的问题。上面提到的mainNavigationController到那时还有状态,但是“本地”navigationController becomesnil:

(lldb) po mainNavigationController.viewControllers
▿ 2 elements
  ▿ 0 : <Vocabulary.MainViewController: 0x7fbd4570dcd0>
  ▿ 1 : <Vocabulary.VocabularyViewController: 0x7fbd4566ce80>

(lldb) po navigationController?.viewControllers
nil

(lldb) po navigationController
nil

在将堆栈/状态保留在 NavigationController 中的同时,我该怎么做才能返回到所需的 ViewController?我应该采取其他方法吗?

坦率地说,我什至不明白为什么场景的 navigationController 首先设置为 nil...

【问题讨论】:

【参考方案1】:

我试过你的方法,真的不行。

您应该从 LearnResultViewController 的导航堆栈中删除 LearnViewController。

navigationController?.viewControllers.removeAll(where:  $0 is LearnViewController )

之后,当您点击返回按钮时,您将返回到 VocabularyViewController。并且后退按钮将在那里。

您不应该为此覆盖 willMove。

【讨论】:

太棒了——就像一个魅力!澄清一下:我现在只是在 LearnResultViewControllerviewDidLoad 中运行提到的代码。通过在弹出之前删除不需要的LearnViewController,我可以弹出回所需的VocabularyViewController(它提供了单词的概述而不是再次学习它们的界面)。感谢您的帮助,弗拉迪斯拉夫!【参考方案2】:

对于 Swift 4.0

for controller in self.navigationController!.viewControllers as Array 
        if controller.isKind(of: DashboardVC.self) 
            _ =  self.navigationController!.popToViewController(controller, animated: true)
            break
        
    

对于 Swift 3

let viewControllers: [UIViewController] = self.navigationController!.viewControllers
for aViewController in viewControllers 
    if aViewController is YourViewController 
        self.navigationController!.popToViewController(aViewController, animated: true)
    

【讨论】:

感谢您的输入,但它并没有解决我的问题...我已经取回了目标 viewController 的一个实例,并且成功地弹回了它——但是当我这样做时, viewController 不再嵌入在 navigationController 中...

以上是关于弹出到 NavigationController 堆栈中的特定 ViewController的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DetailViewController 使用 Tabbar 和 Navigation Controller 弹出到第一个 DetailViewController?

连接到导航控制器时如何将 ViewController 弹出到根目录

从模态弹出到根视图控制器

弹出到导航堆栈中的特定视图控制器

如何关闭视图控制器并快速弹出到根视图控制器?

在 ios 中弹出到下一个 viewController