Storyboard Navigation Controller and Tab Bar Controller

How to use Navigation Controller inside of UITabBarController with Storyboard on Swift

In Interface Builder:

  1. Create an UITabBarController and set it as the initial View Controller.
  2. Create an UITableViewController.
  3. Select the UITableViewController and go to the menu bar > Editor > Embed in > Navigation Controller.
  4. Select your UITabBarController and CTRL-drag from it to the UINavigationController.
  5. Choose Relationship Segue > view controllers.
  6. Now, any View Controller you will add in the UINavigationController stack will be presented in the same UITabBarController.

To perform a segue from the first-in-stack UITableViewController connected to the UINavigationController, to another ViewController you must of course first create another ViewController, create a segue to it in Interface Builder, create an identifier for your segue and in your code perform it by calling the appropriate function in Swift like:

optional func performSegueWithIdentifier(_ identifier: String,
sender sender: AnyObject?)

Here's a sample on how your Interface Builder could look like:
Sample Image

UINavigationController, and TabBarController programmatically (no storyboards)

When combining a UITabBarController and UINavigationControllers, the correct way to set that up is to make the UITabBarController the rootViewController. Each tab of your UITabBarController gets its own UINavigationController. So, if you have 4 tabs, you will create 4 UINavigationControllers.

See: Adding a Navigation Controller to a Tab Bar Interface


Update

Building off of the code you added in your updated question, create a UINavigationController for each of your vc1, vc2, and vc3.

class CustomTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let vc1 = UINavigationController(rootViewController: FirstViewController())
let vc2 = UINavigationController(rootViewController: SecondViewController())
let vc3 = UINavigationController(rootViewController: ThirdViewController())

viewControllers = [vc1, vc2, vc3]
}

}

In each of your ViewControllers, set title to the title you want to be displayed in the navigation bar when that tab is selected:

class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
title = "First"
self.navigationController?.navigationBar.titleTextAttributes =
[NSFontAttributeName: UIFont(name: "Chalkduster", size: 27)!,
NSForegroundColorAttributeName: UIColor.black]
}
}

Swift: How to transition from Navigation Controller to Tab Bar Controler

Okey I found the issue. Thanks @Paulw11 for pointing out that a Tab Bar Viewcontroller can be used just like a normal view controller. The problem was the part "
as? MainViewController", this had to say as? UITabBarController and voila, it worked. For anyone in the future, thats how you do it.

Navigate programmatically through NavigationController-TabBarController-NavigationController

As per my understanding of your code, I think only three lines of code is sufficient

let mainSB = UIStoryboard(name: "Main", bundle: nil)
let tbc = mainSB.instantiateViewController(withIdentifier: “TabBarC”) as? TabBarController
self.window?.rootViewController.present(tbc, animated: true, completion: nil)

Since tab bars view controllers are seems to set in storyboard only. and the first tab of tabbar Controller is selected by default.

EDIT

Other solution for issue of "attempt to present ...."
you can set the flag and in the view controllers viewDidLoad method you can try presenting tabBarViewController same way as in code.

Storyboard navigation controller and tab bar controller

For changing the UINavigationBar title (with no need to create 2 other UINavigationController) you can just use

[self.parentViewController.navigationItem setTitle:@"Title"];

and for adding the right button use

self.parentViewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(myRightButton)];

on viewDidLoad method for each UIViewController referenced from your UITabBarController.

If you want to work with "navigation structures" inside your UIViewController from TabItems so you could edit your BUFViewController.m to that:

#import "BUFViewController.h"

@interface BUFViewController ()

@end

@implementation BUFViewController

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.parentViewController.navigationController setNavigationBarHidden:YES];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(done)];
}

-(void)done{
[self.parentViewController.navigationController popToRootViewControllerAnimated:YES];
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

@end

You have to think as your UITabBarController is inside your parent NavigationController, so you want to hide the parent UINavigationBar and show yours.
After that, you'll be able to back to your table using popToRootViewControllerAnimated: on the parent's UINavigationController.

Hope that helps :)

Viewcontroller's navigation bar is added below navigation controller's navigation bar inside tab bar controller

There is two ways that I found you can resolve this either by presenting tab bar controller modally or hiding navigation bar of a tab bar controller when view loads.

First solution can be achieved like this:

  1. Open Main.storyboard.
  2. Select last segue in this storyboard(one that navigates to Side storyboard).
  3. Make sure that you have Attribute Inspector selected. Now change Kind attribute to Present Modally and Presentation attribute to Full Screen.
    Sample Image

And second solution can be achieved like this:

  1. Create new file by selecting File > New > File > Cocoa Touch Class and press Next.
  2. Change Subclass of: to UITabBarController and name your class to whatever make sense to you.
  3. Then inside of viewDidLoad() paste this navigationController?.navigationBar.isHidden = true in order to hide current navigation bar.
  4. Assign your class to TabViewController in the Side storyboard by selecting TabViewController and changing Class attribute to your class name in Identity Inspector. It should autocomplete when you entering your class name. Press Enter to make sure that you confirm the changes.

Remember to make just one of this two solutions. Which one would it be is up to your needs.

Instantiating deep View Controller with Tab bar and Navigation

Here is how you can do it:

guard let tabBarVC = UIApplication.shared.windows.filter( {$0.rootViewController is UITabBarController } ).first?.rootViewController as? UITabBarController else { return }
tabBarVC.selectedIndex = 0 //you can select another tab if needed
guard let chatVC = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: Constants.Storyboard.chatVC) as? NewChatViewController else { return }
if let navController = tabBarVC.viewControllers?[0] as? UINavigationController {
navController.pushViewController(chatVC, animated: true)
}

You can also pass objects from your notification to your chatVC here before pushing it, in case you need to do that.

Hope this works for you!

How to present navigation controller with tab bar controller

If you want to show MainAreaVC with both NavigationController and TabBarcontroller then you need to present the UITabBarController instead of MainAreaVC. So in storyboard set the Storyboard Id for your TabBarController something like TabbarVC or what ever you want then use it wit instantiateViewController to get UITabBarController.

let tabbarVC = self.storyboard?.instantiateViewController(withIdentifier: "TabbarVC") as! UITabBarController
self.present(tabbarVC, animated: true, completion: nil)


Related Topics



Leave a reply



Submit