TabBarController:总是跳转到根 NavigationController

TabBarController: always jump to root NavigationController

我的应用程序中有以下层次结构:

现在,当用户位于 A3 时,他们可以按另一个 TabBar 项目并跳转到另一个层次结构(例如,B 层)。但是,当他们按下 A 的项目时,他们将跳回到 A3。

我确实希望他们跳转到 A1,这实际上是 A 层次结构中的“父级”UIView。同样,如果他们按 B,他们应该跳到 B1,而不是他们在 B 层次结构中的任何地方。我不是想强迫用户返回例如A1 手动隐藏底栏(来自 TabBarController 的栏)。

实现此目标的最佳方法是什么?

可视化:

    /- A - A1 - A2 - A3
X ---- B - B1 - ...
    \- C - ...

以编程方式,我目前为 X (TabBarController, TabBarControllerDelegate) 和 TableViewControllers A1,...,B1,... 自定义了 类。当用户按下一个项目时,我可以通过调试看到 segue 的目标 VC 是 A/B/... 而不是 A1/B1/... 所以我无法控制这样处理。

编辑:检查下面的故事板图像。

我不确定我是否理解正确,但底线是每当用户点击选项卡栏时,您希望用户能够看到每个 UINavigationController 的根控制器,正确吗?

您提到您已经有一个自定义 TabBarController 那么您是否尝试过 shouldSelect 方法?:

class CustomTabBarController: UITabBarController, UITabBarControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
    }
    
    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
        (viewController as? UINavigationController)?.popToRootViewController(animated: true)
        return true
    }
}

当我在操场上尝试时,这似乎有效。

这是我试过的完整代码:

import PlaygroundSupport
import UIKit

class A: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "A"
        let label = UILabel(frame: CGRect(origin: .init(x: 100, y: 100), size: .init(width: 200, height: 100)))
        label.text = "A"
        self.view.addSubview(label)
        
        let button = UIButton(frame: CGRect(origin: .init(x: 100, y: 200), size: .init(width: 200, height: 100)))
        button.setTitle("Button", for: .normal)
        button.addTarget(self, action: #selector(pressed), for: .touchUpInside)
        button.backgroundColor = .black
        self.view.addSubview(button)
    }
    
    @objc func pressed(_ sender: UIButton) {
        let a1 = A1()
        self.navigationController?.pushViewController(a1, animated: true)
    }
}

class A1: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let label = UILabel(frame: CGRect(origin: .init(x: 100, y: 100), size: .init(width: 200, height: 100)))
        label.text = "A1"
        self.view.addSubview(label)
        
    }
}

class B: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "B"
        let label = UILabel(frame: CGRect(origin: .init(x: 100, y: 100), size: .init(width: 200, height: 100)))
        label.text = "B"
        self.view.addSubview(label)
        
        let button = UIButton(frame: CGRect(origin: .init(x: 100, y: 200), size: .init(width: 200, height: 100)))
        button.setTitle("Button", for: .normal)
        button.addTarget(self, action: #selector(pressed), for: .touchUpInside)
        button.backgroundColor = .black
        self.view.addSubview(button)
    }
    
    @objc func pressed(_ sender: UIButton) {
        let b1 = B1()
        self.navigationController?.pushViewController(b1, animated: true)
    }
}

class B1: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let label = UILabel(frame: CGRect(origin: .init(x: 100, y: 100), size: .init(width: 200, height: 100)))
        label.text = "B1"
        self.view.addSubview(label)
    }

}

class CustomTabBarController: UITabBarController, UITabBarControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
    }
    
    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
        (viewController as? UINavigationController)?.popToRootViewController(animated: true)
        return true
    }
}

let nav1 = UINavigationController(rootViewController: A())
let nav2 = UINavigationController(rootViewController: B())

let tabbarVC = CustomTabBarController()
tabbarVC.view.frame = CGRect(origin: .zero, size: CGSize(width: 500, height: 500))
tabbarVC.addChild(nav1)
tabbarVC.addChild(nav2)

PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = tabbarVC