Swift 中的复杂导航栈

Posted

技术标签:

【中文标题】Swift 中的复杂导航栈【英文标题】:Complex navigation stack in Swift 【发布时间】:2017-06-29 21:20:25 【问题描述】:

我有一个复杂的导航问题,我希望有人能给我一些关于解决这个问题的最佳方法的见解。我一直在谷歌搜索,发现了针对类似问题的多种不同建议,但似乎没有一个能完全确定我的问题。

我有一个 UITabBarController。每个选项卡都设置了自己的导航堆栈,这是应该的。

其中一个选项卡使用具有三个段的 UISegmentedControl。这些段中的每一个都需要有自己的视图控制器和导航堆栈,彼此独立,并且独立于选项卡栏控制器为其选项卡控制的导航堆栈。基本上,它需要像 UITabBarController 的选项卡中的 UITabBarController 一样工作,但将选项卡显示为 UISegmentedControl。

另外,当在每个选项卡的根控制器时,导航堆栈应该是它进来的堆栈,以便它弹出到它进来的表视图。

我遇到了障碍,觉得无论我尝试什么,我都必须进行一些残酷的破解才能继续前进。任何和所有的帮助将不胜感激。

我非常希望能够在 Storyboard 中处理连接,以保持我的 Storyboard 美观,但如果必须在代码中完成,我也可以这样做。

编辑

我有一个解决办法。在基类中:

    private func show(segment: SelectedSegment) 
    var equipmentStoryboard: UIStoryboard!
    switch segment 
    case .SelEquipment:
        equipmentStoryboard = UIStoryboard(name: "EquipmentDetailEquipmentSegment", bundle: nil)
    case .SelHistory:
        equipmentStoryboard = UIStoryboard(name: "EquipmentDetailHistorySegment", bundle: nil)
    case .SelPlans:
        equipmentStoryboard = UIStoryboard(name: "EquipmentDetailPlansSegment", bundle: nil)
    

    if let newSegmentController = equipmentStoryboard.instantiateViewController(withIdentifier: segment.getSegmentIdentifier()) as? EquipmentDetailSegmentsViewController 
        var controllerStack = self.navigationController?.viewControllers
        controllerStack?.removeLast()
        controllerStack?.append(newSegmentController)
        self.navigationController?.setViewControllers(controllerStack!, animated: false)
    

@IBAction func didTapSegmentedControl(_ sender: UISegmentedControl, forEvent event: UIEvent) 
    let newSelectedSegment = SelectedSegment(rawValue: sender.selectedSegmentIndex)

    self.show(segment: newSelectedSegment!)

不过,我对此并不满意。我愿意:

    不必在每次点击段时重新实例化每个控制器。 能够对其进行情节提要(如果没有实际的 UISegmentedControlController 或类似的东西,可能无法实现)

【问题讨论】:

请查看已编辑的问题以了解我的解决方案。欢迎对这种方法提出意见。 如果您的编辑是一个有效的答案,您会回滚该编辑并将其作为答案发布在下面吗?谢谢。 谢谢,这实际上不是解决方案。我尝试了很多不同的东西,无论我尝试什么都遇到了问题。每次再次点击一个段时,我最终都会重新实例化每个应该显示的视图控制器。我确实坚持使用导航堆栈操作,但我仍然强烈认为应该有一种更优雅的方式来做到这一点。如果有某种东西以某种方式采用分段控制并使其表现得像一个标签栏控制器,那就太好了。如果可以的话,我想留下这个开放的可能的进一步答案。 尝试使用每个要显示的视图的容器视图(isHidden 交换)但这不起作用,因为控制器不在任何导航堆栈上,并且向这些控制器添加导航控制器会导致嵌入式导航栏(有趣,我想)。 我尝试在三个控制器之间传递一个控制器数组,以便每次点击一个段时都不会重新实例化每个控制器,但这不起作用,因为我遇到了段控制器未突出显示正确按钮的问题(可能是因为未调用 viewDidLoad)。 【参考方案1】:

我实际上找到了解决问题的正确方法。我必须编写一个自定义系统。我将在某个时候回到这个问题上并继续努力,以便我可以提供一个带有 API 的 github 项目,该 API 可以公开向任何人提供此功能。

基本上,系统会这样做:

可滚动分段控件,可根据需要扩展到任意多个分段。 一个“SegmentNavigationController”,它是一个 UIViewController,因为它包含在点击相应的段时交换到、带到前面、显示和隐藏的视图。 每个段都有自己的导航堆栈,它只是一个视图控制器数组,用于控制当前段中的视图。 自定义动画在向/从导航堆栈推送和弹出项目时发生,使其看起来像一个自然的 ios 控制器。分段控件保留在原位,而新视图动画化。 保留导航,以便在分段之间切换时,您可以在点击不同分段时从中断处继续。 使用 Clean Swift 架构:http://clean-swift.com

我将其发布为答案,因为经过几天的审议,自定义系统是最佳解决方案

当然,这也是可能将该系统扩展为有用且可重用的东西的初步。

【讨论】:

以上是关于Swift 中的复杂导航栈的主要内容,如果未能解决你的问题,请参考以下文章

数据结构 -- 栈

用O的时间复杂度,找到栈和队列中的最小(大)值

Swift 中的复杂 JSON。如何正确获取数据。不同的结构

O时间复杂度实现入栈出栈获得栈中最小元素获得栈中最大元素(转)

在 WP7 Silverlight 应用程序中导航时将复杂对象传递到页面

Codeforces1156 E. Special Segments of Permutation(单调栈,复杂度分析)