显示一个已经在导航堆栈上的视图控制器

Posted

技术标签:

【中文标题】显示一个已经在导航堆栈上的视图控制器【英文标题】:Show a View Controller that is already on Navigation Stack 【发布时间】:2016-11-14 16:23:45 【问题描述】:

我有一个标签栏控制器(带有底部菜单)和一个顶部菜单。问题是我不想将黄色和绿色视图链接到选项卡栏(因为用户将使用顶部菜单而不是底部菜单更改视图)。

我遇到一个问题,每次单击按钮时,都会堆叠一个新的视图实例(所以我最终会得到 V1 -> V2 -> V3 -> V2 -> V4 等)

我的部分解决方案是做这样的事情:

@IBAction func yellowViewButtonAction(_ sender: AnyObject)

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let controller = storyboard.instantiateViewController(withIdentifier: "YelloViewController") as! YelloViewController

    if let viewControllers = navigationController?.viewControllers 
        for viewController in viewControllers 
            // some process
            if viewController is YelloViewController 
                print("View is on stack")
            
         

         let storyboard = UIStoryboard(name: "Main", bundle: nil)
         let controller = storyboard.instantiateViewController(withIdentifier: "YelloViewController") as! YelloViewController
         self.navigationController?.pushViewController(controller, animated: false)
    

我可以看到视图位于导航堆栈上,因为for 中的if 语句是true。问题是,我怎样才能检索它而不是推送同一视图的新实例? (因为除了当前存在的巨大内存问题外,我还丢失了视图中的所有数据)。

我想保持堆栈上的所有内容完好无损。

例子:

V1 -> V2 -> V3 -> V4(当前视图)

如果我从 V4 回到 V1,我仍然希望在导航控制器堆栈上拥有 V4、V3 和 V2。

另一个问题是,如果这个解决方案是苹果可能会拒绝的东西。

感谢您的帮助。

【问题讨论】:

【参考方案1】:

看起来您不使用并且需要导航控制器。每当您调用self.navigationController?.pushViewController(controller, animated: false) 时,该控制器的一个新实例就会进入堆栈。

理想情况下,您会从您导航的视图控制器中调用 popViewController。在创建标签栏控制器的自定义行为时,至少在我看来,很难完全按照您的计划获得导航逻辑。

在这种情况下,我通常会手动显示和隐藏视图控制器。

@IBAction func didPressTab(sender: UIButton) 
        let previousIndex = selectedIndex
        selectedIndex = sender.tag
        buttons[previousIndex].selected = false
        let previousVC = viewControllers[previousIndex]
        previousVC.willMoveToParentViewController(nil)
        previousVC.view.removeFromSuperview()
        previousVC.removeFromParentViewController()
        sender.selected = true
        let vc = viewControllers[selectedIndex]
        addChildViewController(vc)
        vc.view.frame = contentView.bounds
        contentView.addSubview(vc.view)
        vc.didMoveToParentViewController(self)

    

每个“导航按钮”都有唯一的 id 并调用 didPressTab 函数。

我实际上是从本教程中学到的:https://github.com/codepath/ios_guides/wiki/Creating-a-Custom-Tab-Bar

【讨论】:

我确实需要一个导航控制器,因为当我按下黄色和绿色视图时,我仍然可以看到底部栏菜单。就像我说的那样,我希望视图保持不变,如果我弹出,我将丢失视图上的所有数据。 您不需要导航控制器来查看底部菜单栏。查看链接中的教程,您会看到:) 此外,我提供的代码仅移动视图,因此这些视图控制器的“内部”状态保持不变。 我想说的是,我不想要自定义底部菜单栏,因为我已经有了一个。我希望能够在导航控制器堆栈中的视图之间进行更改。 这就是我想说的:) 使用您已经存在的底部菜单。每当您单击菜单元素时,我猜您的代码中的某些操作已执行,因此只需添加我发布的代码以在视图控制器之间切换,根据您的需要对其进行一些调整(变量名称等),它应该可以工作 感谢回购。你的想法实际上给了我另一个想法,我最终使用 Container View 来处理我的所有视图。但是感谢您的想法。【参考方案2】:

弹出视图控制器,直到指定的视图控制器位于导航堆栈的顶部。

参考 - https://developer.apple.com/documentation/uikit/uinavigationcontroller

func popToViewController(UIViewController, animated: Bool) -> [UIViewController]?

【讨论】:

以上是关于显示一个已经在导航堆栈上的视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

管理堆栈上的导航视图

如何展开到导航堆栈上的第一个视图控制器

iOS – 在导航堆栈中显示一个视图控制器

推送导航控制器堆栈后视图不显示

如何导航到推送通知上的视图控制器

在导航堆栈中以模态方式呈现视图控制器