# UITabBarController

## Table of Contents

1. [#what-is-it](#what-is-it "mention")
2. [#how-can-i-set-one-up](#how-can-i-set-one-up "mention")

***

## What is it?

An `UITabBarController` is most commonly used to create the tab switching functionality when developing in UIKit.

{% code fullWidth="true" %}

```swift
@MainActor
class UITabBarController : UIViewController
```

{% endcode %}

{% hint style="info" %} <mark style="color:blue;">`@MainActor`</mark>simply indicates and enforces that this View Controller performs its actions on the main thread. This means that any UI updates made to our tab view controller (tapping on a tab) will always be updated on the main thread. See more about concurrency in [Concurrency](/resources/textbook/coming-soon/concurrency.md).
{% endhint %}

### No, but what is it really?

At its core, an `UITabBarController` is simply a container view controller that allows the user to select between designated child view controllers to display. The selection is done via tab icons that we all know and love, namely something like

<figure><img src="/files/8qgPbkSObxuiLCfEDCGz" alt="" width="375"><figcaption><p>Spotify tabs. Users can easily select between the app's 3 main functionalities.</p></figcaption></figure>

### How are the views set up?

<figure><img src="https://docs-assets.developer.apple.com/published/a0fd9e66d5/1bc595c9-a817-4057-b8b9-ecaa4e8647de.png" alt="" width="375"><figcaption><p>The anatomy of a tab view.</p></figcaption></figure>

Under the hood, the actual view of a tab bar controller (when displaying a piece of content) is simply a *container* that holds 2 things:

1. The actual tab bar view
2. The view that contains your designated custom content

The tab bar view allows for the selection controls and can contain one or more tab items. The custom view contains what you designate as the *root view* for the currently selected tab. The image *above* demonstrates how the views are combine to create a cohesive tab bar interface.

### Why use one?

Developers generally tend to use tab views for myriad of things, such as displaying a bunch of different functionalities and presenting information in different ways. In any case, the important thing to note is that an UITabBarController allows you to manage completely different interfaces in each tab -  i.e. each tab can hold completely different views.&#x20;

A TabBarController is powerful because it handles the tab switching for you - you only need to specify the specific *root views* for each *tab* by instatiating an `UITabBarItem` and it handles the rest of the logic, including updating the UI when the user taps on a tab. Let's dive more into how we can set one up.&#x20;

***

## How can I set one up?

Assuming you have a few *root views* set up (not built out is fine, but as long as the UIViewController classes have at least all been created) that you want to embed as "tabs" in your application. In this case, let's use the Spotify example I snipped earlier for ours. Spotify contains 3 tabs: a home page, a search page, and lastly a library one.&#x20;

Let's first define this home page, as we would with any View Controller we create. You'd do the same with the search and library one.

```swift
import UIKit

class HomeViewController: UIViewController {

    override viewDidLoad() {
        // I like to use other colors when testing
        // to make tab-switching very obvious.
        view.backgroundColor = .systemRed
        ... // Set up this view.
    }
    
}
```

Then, let's define our `UITabBarController` in a new file. Remember, this class acts as the container view that controls the selection of tabs.

<pre class="language-swift"><code class="lang-swift"><strong>import UIKit
</strong>
class TabViewController: UITabBarController {
    
    override func viewDidLoad() {
        super.viewDidLoad()    
    }
    
}
</code></pre>

To create tab bar icons and set up our views, there are a few steps. We can define a function to do so.

<pre class="language-swift" data-overflow="wrap" data-full-width="true"><code class="lang-swift">// MARK: - Setup Tabs
private func setupTabs() {

    // Instantiate view controllers
    let homeVC = HomeViewController()
    let searchVC = SearchViewController()
    let libraryVC = LibraryViewController() // ... etc...
    
    // Customize the tab items. You can insert any image here, using
    // UIImage(named: ...)
<strong>    homeVC.tabBarItem = UITabBarItem(title: "Home", image:     UIImage(systemName: "house"), tag: 0)
</strong>    searchVC.tabBarItem = UITabBarItem(title: "Search", image: UIImage(systemName: "magnifyingglass"), tag: 1)
    libraryVC.tabBarItem = UITabBarItem(title: "Library", image: UIImage(systemName: "books.vertical"), tag: 2)
    // ... Set up other tabs ...
    
    // Set the UITabBarController's View Controllers
    self.setViewControllers([homeVC, searchVC], animated: True)
}
</code></pre>

We can then call this function in the `viewDidLoad()`of our TabViewController class.

```swift
override func viewDidLoad() {
    super.viewDidLoad()
    setupTabs() 
}
```

The basic functionality of a tab view controller is all set up! Now, you can simply create and use it as you would with any other ViewController: `TabViewController()`. If you'd like it to be first thing the user sees when opening the app, you can modify the `SceneDelegate.swift` file to set it as the app's root view controller like so, which follows [Xcode Project Setup](/resources/tool-guides/xcode-project-setup.md).

{% code overflow="wrap" %}

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

{% endcode %}

If you want a certain tab to be the "main" tab (i.e. the one that the tab view opens on), you can do so via the tab view's `.selectedIndex` property.&#x20;

```swift
private func setupViews() {
    /// ... Other code ...
    // Designate the initial index. 0 refers to the first tab. 
    selectedIndex = 0 
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ios-course.cornellappdev.com/resources/tool-guides/tab-views/uitabbarcontroller.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
