TabBarController disappears when I segue back to the view from another view - ios

I have a viewController that is embedded in a nav controller. This nav controller is then embedded in a tab bar controller.
I have another viewController that is not supposed to be accessible from the tabBarController. It should only be accessible from the first viewController using a button. From the secondViewController, I made a UIBarButtonItem to move back to the original view. From the first view to the second view and vice versa, I used a Storyboard reference to move to and from from the views.
However, when I move from the first view to the second view, the tab bar controller disappears (like it should). When I move back to the first view, the tab bar controller disappears and I cannot move between tabs anymore.
I tried including:
self.hidesBottomBarWhenPushed = false
on the first view and
self.hidesBottomBarWhenPushed = true
on the second view
and nothing seems to work. The tab bar controller disappears every time i move from the second view to the first view.

You are following a wrong hierarchy. You are actually using seagues to go back and forth. This creates a new instance every time you try to come back to the first controller.
Let's make it clear:
You need to follow the below approach:
1 You have two controllers A and B.
2 Use self.hidesBottomBarWhenPushed = true in viewDidLoad or viewWillAppear of controller A.
3 Controller A is embedded in a navigation controller which is further embedded in a UITabBarController.
Tapping a button in controller A, you need to push to controller B. So you can use segue for this or you can do it programatically like:
let controllerB = B()
A.navigationController?.pushViewController(controllerB, animated: true)
4 Go Back to Controller A on the tap UIBarButtonItem. So your code in the action of UIBarButtonItem should be something like:
self.navigationController?.popViewController(animated: true)
Remember you should not should segue to go back to the previous controller.

you should use
override func viewWillDisappear(_ animated: Bool) {
self.tabBarController?.tabBar.isHidden = false
}
in that controller where the back button is placed, I am using the exact scenario in one of the my app.

Related

Two NavigationBar Showing

Hi I am new to Swift and am trying to build an app with multiple Views..
My first View(initial view) is embedded in navigation controller.
My Second View is embedded in Tab Bar Controller
My Third View is again embedded in a Navigation Controller.
The problem is that on my third view I see to navigation Controller with the top one taking me back to First View and the below one taking me to Second View.
Is it an incorrect way of doing this? I want to get rid of navigation bar that came from 1st view.
Thanks in anticipation.
PS : I had initially not attempted Navigation Bar on 3rd View.. but the problem was that I am also not able to map Bar Button Item and hence to embed the 3rd View too in a separate Navigation Controller
While it shows perfect in Xcode.. it shows 2 NavBar on the simulator
Not an elegant solution but still this can solve your problem. On your controller embed to UITabBarController where you have added Next Button. Add the below code on that controller class.
On ViewWillappear add show nav bar and on viewDidDisappear hide nav bar as shown in below code
ON viewWillAppear:
override func viewWillAppear(_ animated: Bool) {
self.navigationController.navigationBar.isHidden = false
}
ON viewDidDisappear:
override func viewDidDisappear(_ animated: Bool) {
self.navigationController.navigationBar.isHidden = true
}

Tabbar is not showing up after popToRootViewController

In my application, I hide tabbar by setting hidesBottomBarWhenPushed property of UIViewController. I'm not sure this behavior is designed or not, when I called popToRootViewController to pop all view controller stack, tabbar did not show properly if I pushed same view controller after. Even I tried to show tabbar by setting isHidden property after I called popToRootViewController but it didn't work neither. Weird part is, after tabbar disappeared, I pushed same view controller and I could see the tabbar when I tried to pop the view controller (not popToRootViewController) by using gesture to pop (swipe to pop). Though it disappeared when transition was completed.
FYI, this is step by step to produce this behavior.
init tabbar and navigation controllers on two tabs.
push view controller (hidesBottomBarWhenPushed is true) on one tab's navigation controller
pop all view controller from the navigation controller by calling popToRootViewController
4 change tab index by setting selectedIndex on tabbarController
push the same view controller
How does hidesBottomBarWhenPushed property work in detail to show/hide tabbar?
I'll talk about the problem in my app.
For every pages, I'll edit the self.navigationController?.navigationBar.isHidden and self.tabBarController?.tabBar.isHidden = false to guarantee the state of tabBar and navigationBar in the viewWillAppear.
Sample
// In this viewController, I'll show the navigation bar and hide tab bar
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.isHidden = false
self.tabBarController?.tabBar.isHidden = true
}
The navigationBar and tabBar can keep their state from last view controller when you push a new one or pop a old one. So it will let we set in every view controller to control and ensure its state as I wish.

how to hide tab bar when push and show tab bar when back

I want
view controller 1: tab bar is showed
view controller 2: tab bar is showed
view controller 3: tab bar is not showed.
I wrote
// prepareForSegue in view controller 1,
let upcoming = segue.destinationViewController as! viewcontroller3
upcoming.hidesBottomBarWhenPushed = true
// prepareForSegue in view controller 3,
let upcoming = segue.destinationViewController as! viewcontroller2
self.hidesBottomBarWhenPushed = true
When I go to view controller 3 from view controller 1, tab bar is not showed. Then, I go to view controller 2 from view controller 3, tab bar is showed. But when I tap back in view controller 2, tab bar is showed in view controller 3. self.hidesBottomBarWhenPushed = true does not make sense to me. But, I couldn't figure what I should do to fix that. Any suggestions? Thanks.
The way to hide the tab bar is - In the place where you are pushing the next view controller do that:
self.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(controllerToPush, animated: true)
self.hidesBottomBarWhenPushed = false
This will make sure the tab bar is hidden for the pushed view and when you pop back the bar will show again. No back button logic, no viewDidLoad or similar, nothing else. This should be enough.
The same should work for objective-c
Now ( 21/02/2018 ) you can also check the option in the Storyboard for each controller that you do not want to show the bottom bar. This will help clean up the code and you do not need to set anything in the controller that you are pushing from.
Edit: That solved the problem.
It makes sense that the tab bar is appearing because when going clicking back from VC2 to VC3, nothing is telling VC3 to hide its Tab Bar.
I think you have 2 solutions here (but haven't tested any):
You can try doing something like this guy did. He added the hidesBottomBarWhenPushed logic in BackButtonPressed Handler.
In VC3, do self.tabBarController?.tabBar.hidden = true in ViewDidLoad or viewWillAppear
#stan has almost the right answer. As he mentioned, you want to set to set hidesBottomBarWhenPushed = true if you want the bottom bar to be hidden. However, you should set it on the controller to be pushed as follows.
controllerToPush.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(controllerToPush, animated: true)
Set hidesBottomBarWhenPushed = true in the controller that you want to hide.
For hide all controllers put into prepare for segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
segue.destination.hidesBottomBarWhenPushed = true
}

Adding a navigation controller programmatically for the second VC

In my storyboard, I have setup a navigation controller points to my MainVC, and it works just fine.
And now, I'm trying to add another view called "HelpVC", and I created one in the storyboard. It automatically shows the navigation bar on the top.
(MainVC segues to HelpVC)
However, I did everything else in code.
I had initWithView in the HelpVC which draws out the interface, BUT the navigation bar does not show up, so I can't go back to that previous view controller.
How do I make sure that the navigation bar shows up and works just like other view controllers? (segue back to the last view?)
It is not very clear from the post, but as I understood, you may want to try:
override func viewWillAppear(_ animated: Bool){
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = false
}

Edit button not displayed in UITabBarController's MoreNavigationController

A UITabBarController is being pushed onto the stack:
let presenter = presentingViewController as! UINavigationController
let tabvc = UITabBarController()
tabvc.viewControllers = vcs
tabvc.customizableViewControllers = vcs
presenter.pushViewController(tabvc, animated: true)
Once presented the more tab button correctly shows, but the edit button to rearrange the tab bars does not. According to the docs on the MoreNavigationController:
The interface for the standard More item includes an Edit button that
allows the user to reconfigure the tab bar. By default, the user is
allowed to rearrange all items on the tab bar. If you do not want the
user to modify some items, though, you can remove the appropriate view
controllers from the array in the customizableViewControllers
property.
My guess is that the tab bar is not happy being in a navigation controller. Any ideas on bringing the edit button back?
You can have both a UINavigationController and a UITabBarController ; using Storyboard helps understand the issue better, any of these solutions will work:
Start out with a UITabBarController as initial view controller
Use presentViewController instead of pushViewController
Use a modal Storyboard segue to perform a modal presentation
Swap out the rootViewController dynamically
Initial View Controller Design
When the Tab Bar Controller is initial View Controller, the Edit button is displayed normally.
Pushed Design
Another Navigation Controller is initial View Controller, using one of 5 adaptive Action Segue:
Show
Custom
-> No Edit button, since it is in direct conflict with the parent UITableViewController.
Show Detail
Present Modally
Popover Presentation
-> Edit button displayed as expected.
Code
1. Program Modal
Using the exact code presented in the question, change the last line:
let presenter = presentingViewController as! UINavigationController
let tabvc = UITabBarController()
tabvc.viewControllers = vcs
tabvc.customizableViewControllers = vcs
presenter.presentViewController(tabvc, animated: true, completion: nil)
2. Storyboard Modal
keeping with the Storyboard theme, create a segue of the correct type, assign an identifier (i.e. presentModallySegue) and the 5 lines above become this single line:
self.performSegueWithIdentifier("presentModallySegue", sender: self)
3. root Swap
A more drastic solution involves swapping out the root view controller at the window level:
let tabvc = UITabBarController()
tabvc.viewControllers = vcs
tabvc.customizableViewControllers = vcs
self.view.window!.rootViewController = tabvc
Conclusion
Either change your design to adopt the Tab Bar Controller as the initial View Controller, or present the Tab Bar Controller modally.
The reason is that navigation bar of your presenter overlaps with the navigation bar of More section.
If you don't show the navigation bar for you navigation controller, you will be able to see the Edit button again when you tap on the More tab.

Resources