Reputation: 169
I have the following hierarchy in my app:
TabBarController
(X)NavigationController
(A, B, C...)NavigationController
s starts a hierarchy (e.g. A1, A2, A3,...) of TableViewController
sNow when the user is, say, in A3, they can press another TabBar
item and jump to another hierarchy (say, the one of B). However, when they press the item for A, they will jump back to A3.
What I do want to happen, is for them to jump to A1 instead, which is essentially the "parent" UIView
in the A hierarchy. Similarly, if they press B, they should jump to B1, not to wherever they were in the B hierarchy. I do not want to force the user to go back to e.g. A1 manually by hiding the bottom bar (the one from the TabBarController
).
What is the best way to achieve this?
For visualisation:
/- A - A1 - A2 - A3
X ---- B - B1 - ...
\- C - ...
Programmatically, I currently have custom classes for X (TabBarController, TabBarControllerDelegate
) and the TableViewController
s A1,...,B1,... . When the user presses an item, I can by debugging see that the target VC for the segue would be A/B/... and not A1/B1/... so I cannot control the process this way.
EDIT: check storyboard image below.
Upvotes: 1
Views: 1167
Reputation: 4023
I'm not sure if I understood you correctly, but the bottomline is whenever the user taps on the tab bar you want the user to be able to see the root controller of each of the UINavigationController
, correct?
You mentioned that you already have a custom TabBarController
so have you tried the shouldSelect
method?:
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
}
}
This seems to be working when I tried it on my playground.
Here's the full code I tried it with:
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
Upvotes: 3