Creating iOS Tab Bar Controller Programmatically with UIKit

Tab bar controllers are common to be found on mobile applications considering the convenience they offer in terms of switching between screens. Here, I am going to show you how to create a tab bar controller programmatically in Swift (without using Storyboard).

The main thing that we need to understand is that this tab bar controller holds other navigation controllers, that also become the container for other view controllers. Thus, creating the view controllers is a good point to begin with.

I create two separate files for each view controller, I name them HomeVC and FavoritesVC. The view controllers simply show plain background color.


import UIKit

class HomeVC: UIViewController {
    override func viewDidLoad() {

        view.backgroundColor = .systemPink


import UIKit

class FavoritesVC: UIViewController {
    override func viewDidLoad() {
        view.backgroundColor = .systemBlue

Then, in SceneDelegate.swift, we create three functions as follows. The goal of this block of code is to create one tab bar controller and two navigation controllers. As I stated earlier, the first one will 'hold' the other two.

func createTabBar() -> UITabBarController {

    let tabBar = UITabBarController()
    let homeNC = createHomeNavigationController()
    let favoritesNC = createFavoritesNavigationController()

    tabBar.viewControllers = [homeNC, favoritesNC]

    return tabBar

func createHomeNavigationController() -> UINavigationController {

    let homeVC = HomeVC()
    homeVC.title = "Home"
    homeVC.tabBarItem = UITabBarItem(title: "Home", image: UIImage(systemName: "house"), tag: 0)

    return UINavigationController(rootViewController: homeVC)

 func createFavoritesNavigationController() -> UINavigationController {

    let favoritesVC = FavoritesVC()
    favoritesVC.title = "Favorites"
    favoritesVC.tabBarItem = UITabBarItem(tabBarSystemItem: .favorites, tag: 1)

    return UINavigationController(rootViewController: favoritesVC)

Making separate functions with specific functionality like above is my personal preference. If you find it not too efficient, then you can write the code with the style you are happy with.

Next, inside the uppermost boilerplate function, still, in SceneDelegate.swift file, we add the following lines of code:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

   guard let windowScene = (scene as? UIWindowScene) else { return }

   window = UIWindow(frame: windowScene.coordinateSpace.bounds)
   window?.windowScene = windowScene

   let tabBar = createTabBar()
   window?.rootViewController = tabBar

We need to set the windowScene considering that we are not using Storyboard. Finally, we set the instance of our tab bar controller to the rootViewController of the window. The final result will pretty much look like this:


Article cover photo by Kate Torline on Unsplash

No Comments Yet