iPhone
UITableViewController
Navigation bar
iOS development
modal presentation

iPhone Show modal UITableViewController with Navigation bar

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

If you present a UITableViewController directly, UIKit shows the table but not a navigation bar. The standard solution is to embed the table controller inside a UINavigationController and present that navigation controller modally.

Wrap the Table in a Navigation Controller

UITableViewController manages rows, sections, selection, and refresh behavior. It does not own navigation chrome. In UIKit, the navigation bar belongs to UINavigationController, which is why the bar appears only after you wrap the table screen in one.

This separation is useful because the same table controller can work in two modes. You can push it onto an existing navigation stack or present it modally in its own temporary stack.

Presenting the Modal Screen

The following Swift example creates a host controller, builds the table controller, wraps it in a navigation controller, and presents it:

swift
1import UIKit
2
3final class HostViewController: UIViewController {
4    override func viewDidLoad() {
5        super.viewDidLoad()
6        view.backgroundColor = .systemBackground
7
8        let button = UIButton(type: .system)
9        button.setTitle("Show options", for: .normal)
10        button.addTarget(self, action: #selector(showOptions), for: .touchUpInside)
11        button.translatesAutoresizingMaskIntoConstraints = false
12
13        view.addSubview(button)
14        NSLayoutConstraint.activate([
15            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
16            button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
17        ])
18    }
19
20    @objc private func showOptions() {
21        let tableController = OptionsTableViewController(style: .insetGrouped)
22        let navigationController = UINavigationController(rootViewController: tableController)
23        navigationController.modalPresentationStyle = .formSheet
24        present(navigationController, animated: true)
25    }
26}

The modal table controller configures its own title and dismissal button:

swift
1import UIKit
2
3final class OptionsTableViewController: UITableViewController {
4    private let options = ["Profile", "Notifications", "Privacy", "Help"]
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8        title = "Settings"
9        navigationItem.leftBarButtonItem = UIBarButtonItem(
10            barButtonSystemItem: .cancel,
11            target: self,
12            action: #selector(close)
13        )
14    }
15
16    @objc private func close() {
17        dismiss(animated: true)
18    }
19
20    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
21        options.count
22    }
23
24    override func tableView(
25        _ tableView: UITableView,
26        cellForRowAt indexPath: IndexPath
27    ) -> UITableViewCell {
28        let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
29        cell.textLabel?.text = options[indexPath.row]
30        return cell
31    }
32}

The key detail is that you present navigationController, not tableController.

Picking the Right Presentation Style

On recent iPhone versions, modal screens often appear as sheets instead of taking over the full display. That behavior is controlled by modalPresentationStyle.

Use .pageSheet or .formSheet for short flows such as choosing an option list or editing a small settings group. Use .fullScreen when the modal screen acts like a separate task and should feel more immersive.

If the user needs a confirmation action, add a done button with navigationItem.rightBarButtonItem. Because the bar belongs to the modal navigation stack, the button appears automatically once the modal is shown.

Storyboard-Based Apps

The same pattern applies when the table controller comes from a storyboard. Instantiate the controller, wrap it, and present the wrapper:

swift
1@IBAction func showList(_ sender: Any) {
2    let storyboard = UIStoryboard(name: "Main", bundle: nil)
3    let tableController = storyboard.instantiateViewController(
4        withIdentifier: "OptionsTableViewController"
5    )
6    let navigationController = UINavigationController(rootViewController: tableController)
7    present(navigationController, animated: true)
8}

This keeps the presentation code consistent whether you build the UI in code or Interface Builder.

Common Pitfalls

The first mistake is presenting the table controller by itself. That shows the rows, but no navigation bar appears because nothing is managing navigation.

Another issue is forgetting a dismissal control. A modal screen that has a title bar but no cancel or done action quickly becomes awkward.

Developers also get confused by default sheet behavior on modern iOS versions. If the modal does not cover the whole screen, it may simply be using the system default presentation style.

Finally, keep row rendering lightweight. Rebuilding expensive views in cellForRowAt can make a small modal list feel sluggish.

Summary

  • A UITableViewController does not create a navigation bar on its own.
  • Wrap the table controller in UINavigationController before presenting it modally.
  • Add cancel or done actions through navigationItem.
  • Set modalPresentationStyle explicitly when the visual behavior matters.
  • The same wrapping pattern works for programmatic and storyboard-created controllers.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.