I have an issue with the hidesBottomBarWhenPushed.
It works correctly when pushed (hides tab bar) and when popped (shows tab bar). But I have this little gem:
- There is a UITabBarController which has a UINavigationController as tab with in it a single UIViewController
- Push a new UIViewController on the stack, this view controller has
hidesBottomBarWhenPushedset to true in the init. The tab bar is hidden correctly - There is a button in this view that performs two actions
- Present a new view controller modally (full screen, for sheet presentation this works)
- Pop the current view controller
- Dismiss the modally presented view
- The initial UINavigationController is shown with its child, the tab bar is still hidden however
So sadly since there are no official functions to call on the UITabBarController to hide or show the UITabBar I don't see a good way to fix this. There is also no function to reevaluate the current state.
If the presentation is slightly delayed all works fine (but well there are some stakeholders who don't want that...)
So this is the complete code that reproduces the bug (assumes a new project with a storyboard where you have a UITabBarController as the entry point, in it a single UINavigationController with the ViewController as its child)
Please forgive the 'uglyness', it is just simple demo code
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
tabBarController?.tabBar.isTranslucent = false
view.backgroundColor = .red
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.navigationController?.pushViewController(VC2(), animated: true)
}
}
}
class VC2: UIViewController {
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
hidesBottomBarWhenPushed = true
navigationItem.leftBarButtonItem = UIBarButtonItem(systemItem: .close, primaryAction: UIAction(handler: { _ in
let nvc = self.navigationController
let vc = UINavigationController(rootViewController: VC3())
vc.modalPresentationStyle = .fullScreen
// With a delay it all works fine
// DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
nvc?.present(vc, animated: true)
// }
self.navigationController?.popViewController(animated: true)
}), menu: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
}
}
class VC3: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
navigationItem.leftBarButtonItem = UIBarButtonItem(systemItem: .close, primaryAction: UIAction(handler: { _ in
self.dismiss(animated: true)
}))
}
}
Seems that a 'hacky' solution is to make a modification to the 'owning' UINavigationController
For me this works without any visual artifacts, but it is also a bit hacky which is always a questionable solution.