hide tab bar in view with push - swift

I have a tabBar + NavigationViewController. The Tab bar has collection view with cells(Say view1) and with cells a push seague is implemented to another view(Say view2).
In view2 I want to have a navBar but no tab bar.
I tried
self.tabBarController?.tabBar.hidden = true,
it worked fine for view2 but when I went back to view1 by back button the tab was still hidden( even after in view1 class I added self.tabBarController?.tabBar.hidden = false in viewDidLoad func).
How can i make the tab bar reappear in view1?
I'm working in swift.

Make sure to check this option only on the ViewController whose tab
bar you wish to be hidden.
Thanks to iHarshil for the suggestion.

In the viewDidload set the UIViewController hidesBottomBarWhenPushed to yes:
self.hidesBottomBarWhenPushed = YES;
This way the UINavigationController takes care of hiding the tab bar.

Use in prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController = segue.destinationViewController;
destViewController.recipeName = [recipes objectAtIndex:indexPath.row];
// Hide bottom tab bar in the detail view
destViewController.hidesBottomBarWhenPushed = YES;
}
}

Bruno Fernandes's answer in Swift:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "YourSegueIdentifier" {
let destinationController = segue.destinationViewController as! YourViewController
destinationController.hidesBottomBarWhenPushed = true
}
}
This was the answer that worked for me. Putting hidesBottomBarWhenPushed in the viewDidLoad method didn't work.
Thanks Bruno!

In my case, I use hidesBottomBarWhenPushed before I push the destination view controller.
func showSecondViewController() {
let vc = SecondViewController()
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
}

You have to work with viewWillAppear or viewDidAppear. viewDidLoad will be called when view1 is loading (showing) the first time. If you move from view1 to view2 and back the viewDidLoad won't be called again. Therefore you have to use viewWillAppear or viewDidAppear like
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.tabBar.hidden = false
}
Put this code in your view1 controller. The viewWillAppear or viewDidAppear will be called every time navigating back to view1

if you want to hide TabBarController Bottom Bar : #Swift 3
In YourViewController : in ViewDidLoad() method
self.tabBarController?.tabBar.isHidden = false

Related

How to do popViewController from another class?

My app has a TabBarController. Each tabBarItem relates to a ViewController embedded in a NavigationController.
When in first tabBarItem and selecting another tabBarItem I want to do some stuff before moving to the selected ViewController. Therefore I created a class for my tabBarController and made it UITabBarControllerDelegate.
What I want to do is present an alert with two buttons; button A cancels the move to the selected viewController and button B lets the move happen.
My problem is that when button B is pressed, I want to popToRootViewController. I gave the navigationController a storyboardID and tried to instantiate it like shown below.
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if let alert = self.storyboard?.instantiateViewController(withIdentifier: "ActiveSessionWarningAlert") as? ActiveSessionWarningAlert {
alert.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
alert.modalTransitionStyle = UIModalTransitionStyle.flipHorizontal
let alertWasDismissed: (Bool) -> Void = { userWantsToMoveToSelectedViewController in
if userWantsToMoveToSelectedViewController {
if let navContr = self.storyboard?.instantiateViewController(withIdentifier: "firstNavContr") as? UINavigationController {
navContr.popToRootViewController(animated: true)
}
tabBarController.selectedViewController = viewController
}
}
alert.alertWasDismissed = alertWasDismissed
self.present(alert, animated: true, completion: nil)
}
return false
}
Everything works as expected, but the popToRootViewController doesn't seem to occur; when selecting the first tabBarItem again the same viewController that was 'active' when we left the item is still showing.
I checked so that the viewController I want to pop is actually in the navigation stack and that the navContr != nil.
What am I missing?
You don't say so, but I'm assuming that the alertWasDismissed closure you pass to your alert view controller gets invoked when the user dismisses the alert.
The problem with your closure is this bit:
if let navContr = self.storyboard?.instantiateViewController(withIdentifier: "firstNavContr") as? UINavigationController
Any time you call instantiateViewController(withIdentifier:), you are creating a brand new, never before seen instance of a view controller (a navigation controller in this case.) That navigation controller has nothing to do with the one that belongs to the current tab that you are trying to dismiss. It doesn't have anything in it's navigation stack other than the root view controller that is defined in the storyboard.
What you need to do is find the navigation controller of the current tab in your tab bar controller's tabBarController(_:shouldSelect:) method, and pass that navigation controller to your alertWasDismissed closure.
At the time the tabBarController(_:shouldSelect:) method is called, the tab bar controller's selectedViewController should contain the current view controller. Replace the line above with:
if let navContr = tabBarController.selectedViewController? as? UINavigationController {}
That should work.

Display title on modally presented view in Swift 5

I am using Xcode 11.2.1, Swift 5, and have a view that is presented Modally. Via storyboard I added a navigation bar and have two navigation items, left, cancel, right, save. I am trying to get the title of the view to display. I have tried via viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "New " + costumeChoice
imageFromFileButton.alpha = 0.5
imageFromFileButton.isEnabled = false
costumeImageView.image = UIImage(named: "PauPlaceholder")
}
I have tried "self.navigationItem.title = "New " + costumeChoice" through viewWillAppear and through viewDidAppear, but no luck.
What am I missing?,
You have to present the NavigationController which embedded your ViewController, that way a navigationBar will be presented.
For example:
Assuming that your current ViewController is CurrentViewController
and viewController which you want to present is DestinationViewController
In order to present the destinationController you have to do this: -
// self ==> CurrentViewController
self.present(UINavigationController(rootViewController:DestinationViewController(), animated: true)

How to press "Back" button in UINavigationController programmatically

I have a UIViewController called FriendsViewController inside a UINavigationController. And a second UIViewController called FriendsDetailedViewController. When navigating from the first view controller to the second, I want to programmatically press the Back button when needed. How to do this?
Simply use
[self.navigationController popViewControllerAnimated:YES]
from FriendsDetailedViewController. Your view will be popped out i.e. the behavior of back button.
Note that it returns UIViewController on normally, and returns nil if there is nothing to pop.
If by pressing "Back" button you mean just to go to the previous view controller, you can just call:
[self.navigationController popViewControllerAnimated:YES];
Here is the swift method
if let navController = self.navigationController {
navController.popViewControllerAnimated(true)
}
Swift 5
self.navigationController?.popViewController(animated: true)
Usage in a code snippet:
func unwindViewController() {
self.navigationController?.popViewController(animated: true)
}
1) When you pop in current NavigationController Then
In Swift
self.navigationController?.popViewControllerAnimated(true)
Objective C
[self.navigationController popViewControllerAnimated:YES];
2) When you back another Navigation controller Then
In Swift
let story = UIStoryboard(name: "Main", bundle: nil)
let pushVC = story.instantiateViewControllerWithIdentifier("PushVC")
let navigation = story.instantiateViewControllerWithIdentifier("homeNavigation") as! UINavigationController
navigation.pushViewController(pushVC!, animated: true)
In Objective C
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"storyBoardName" bundle:nil];
pushVC* ObjectOfPushVC = [storyboard instantiateViewControllerWithIdentifier:#"pushVC"];
[self.navigationController pushViewController:ObjectOfPushVC animated:YES];
Here is how I did it in Swift 3
_ = self.navigationController?.popViewController(animated: true)
_ is used to suppress the ugly warning generated by XCode.

When using hidesBottomBarWhenPushed, i want the tab bar to reappear when i push another view

I have a navigation controller. For one of the views i want to hide the bottom tab bar, so it gets the max possible screen real estate. To do this, i have:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.hidesBottomBarWhenPushed = YES; // To hide the tab bar
}
return self;
}
But for the next view that i push on the stack, i want the tab bar to reappear. Is there a way to do this?
As of iOS5, there's a very easy means of accomplishing this. It's essentially the same method as Deepak, but there aren't any artifacts with the animation - everything looks as expected.
On init, set
self.hidesBottomBarWhenPushed = YES;
just as you have above. When it's time to push the new controller on the stack, it's as simple as:
self.hidesBottomBarWhenPushed = NO;
UIViewController *controller = [[[BBListingController alloc] init] autorelease];
[self.navigationController pushViewController:controller];
self.hidesBottomBarWhenPushed = YES;
It's important to reset the value to YES after the controller has been pushed in order to re-hide the bar when the user taps the Back button and the view comes back into view.
I'm have solved this problem like that:
Almost all my ViewControllers are children of BaseViewController.
So, example:
class BaseVC: UIViewController {
final override var hidesBottomBarWhenPushed: Bool {
get {
if navigationController?.viewControllers.last == self {
return prefersBottomBarHidden ?? super.hidesBottomBarWhenPushed
} else {
return false
}
} set {
super.hidesBottomBarWhenPushed = newValue
}
}
private(set) var prefersBottomBarHidden: Bool?
}
Just override variable "prefersBottomBarHidden" in ViewController where BottomBar should be hidden:
override var prefersBottomBarHidden: Bool? { return true }
It's been a while since this question was asked, but none of these answers address using Storyboard segues. It turns out to be pretty easy:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "MyViewControllerIdentifier" {
// Hide the tabbar during this segue
hidesBottomBarWhenPushed = true
// Restore the tabbar when it's popped in the future
DispatchQueue.main.async { self.hidesBottomBarWhenPushed = false }
}
}
One can make it reappear but it will result in an incorrect animation. Page comes in left and the bottom bar right. So it is probably not the behavior you want. But in the same controller, do self.hidesBottomBarWhenPushed = NO; before pushing the next view controller in.
Case one:
To hide UITabbarController in a cetain UIVIewController, for example while calling self.performSegueWithIdentifier("Identifier", sender: self), it is necesssary prior to to that, set self.hidesBottomBarWhenPushed = true flag. And after self.hidesBottomBarWhenPushed = false flag. But we have to understad that through one UIViewController, UITabbarController will re-appear and, in case if you need to use UITabbarController with single UIViewControler, it wont yield right result.
in the FirstItemViewController
#IBAction func pushToControllerAction(sender: AnyObject) {
self.hidesBottomBarWhenPushed = true
self.performSegueWithIdentifier("nextController", sender: self)
self.hidesBottomBarWhenPushed = false
}
Case Two:
To hide UITabbarController in a certain UIVIewController, after which a UITabbarController should be popped, it is necessary, for example, while calling self.performSegueWithIdentifier("nextController", sender: self) , to set self.hidesBottomBarWhenPushed = true before the method. Alse willMoveToParentViewController(parent: UIViewController?) in the method should be configured as it shown in the code example.
in the first UIViewController "FirstItemViewController"
#IBAction func pushToControllerAction(sender: AnyObject) {
self.hidesBottomBarWhenPushed = true
self.performSegueWithIdentifier("nextController", sender: self)
}
in the next UIViewController "ExampleViewController"`
override func willMoveToParentViewController(parent: UIViewController?) {
if parent == nil {
var viewControllers = self.navigationController!.viewControllers
if ((viewControllers[viewControllers.count - 2]).isKindOfClass(FirstItemViewController.self)) {
(viewControllers[viewControllers.count - 2] as! FirstItemViewController).hidesBottomBarWhenPushed = false
}
}
}
Swift 3 code:
let viewControllers = self.navigationController!.viewControllers
if ((viewControllers[viewControllers.count - 2]) is (FirstItemViewController)) {
(viewControllers[viewControllers.count - 2] as! FirstItemViewController).hidesBottomBarWhenPushed = false
}
Test project
In a root view controller "A" (which is showing the tabBar), when it comes time to show another view controller "B" where no tabBar is wanted:
self.hidesBottomBarWhenPushed = YES; // hide the tabBar when pushing B
[self.navigationController pushViewController:viewController_B animated:YES];
self.hidesBottomBarWhenPushed = NO; // for when coming Back to A
In view controller B, when it comes time to show a third view controller C (tabBar wanted again):
self.hidesBottomBarWhenPushed = NO; // show the tabbar when pushing C
[self.navigationController pushViewController:viewController_C animated:YES];
self.hidesBottomBarWhenPushed = YES; // for when coming Back to B

Adding a NavigationBar to UITableViewController programmatically?

I am trying to create a uitableviewcontroller as a modal viewcontroller to edit some settings. I am creating the tableviewcontroller in code and the thing i am struggling with currently is how to correctly add a navigation bar to the controller which will have a "Done" button on it that:
a) doesnt appear on top of the tableview and
b) does not scroll with the tableview??
This happens when i add the navbar to the contoller with:
[self.view addSubview:navigationBar];
This adds a navbar to the controller which goes on top and obscures the tables first row and also scrolls with the view?
I also thought about simply using a uiviewcontroller with a separate tableview however i like the funcitonality of automatically scrolling the tableview when editing a textfield that the tableviewcontroller gives you. Just cant figure how to setup this navbar??
thx
Just create UINavigationcontroller as the modal viewcontroller, and add the tableview as its root view controller.
Use Navigation controller as modalviewController(as suggested in the other answer). Here is the code:
UINavigationController *Controller = [[UINavigationController alloc] init];
//LoginViewController is a sub class of UITableviewController
LoginViewController *controller = [[LoginViewController alloc] init];
Controller.viewControllers=[NSArray arrayWithObject:controller];
[self presentModalViewController:Controller animated:YES];
[controller release];
[Controller release];
In Swift:
AppDelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
/*
#1. Instantiate a navigation controller and add the table view controller
as a child view controller.
*/
let navigationController = UINavigationController()
// Instantiate your desired ViewController
let storyboard = UIStoryboard(name: UIStoryboardName.Main.rawValue, bundle: nil)
let tableViewController = storyboard.instantiateViewControllerWithIdentifier("TableViewControllerID")
navigationController.addChildViewController(tableViewController)
/*
#2. Then we set the title of the navigation bar and add two bar button items.
*/
// We set the title of the navigation bar.
tableViewController.navigationItem.title = "My Title"
// Create left and right button for navigation item.
let leftButton = UIBarButtonItem(title: "Save", style: UIBarButtonItemStyle.Plain, target: tableViewController, action: "saveButtonClicked:")
let rightButton = UIBarButtonItem(title: "Right", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
// Create two buttons for the navigation item.
tableViewController.navigationItem.leftBarButtonItem = leftButton
tableViewController.navigationItem.rightBarButtonItem = rightButton
/*
#3. To finish we set the root view controller with the navigation controller.
*/
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
return true
}
TableViewController.swift
// Method called when the user clicks on the Save bar button item.
func saveButtonClicked(sender: UIBarButtonItem) {
// Do something.
print("Save bar button item has been clicked!!!")
}