What is UINavigationController?
UINavigationController
is a container view controller that manages a stack of view controllers to provide hierarchical navigation in an iOS app. It allows users to navigate between screens using a navigation bar with a back button.
1. Key Features of UINavigationController
✅ Manages a Stack of View Controllers – Enables hierarchical navigation.
✅ Provides a Navigation Bar – Displays titles, buttons, and actions.
✅ Supports Push and Pop Transitions – Moves forward and backward between screens.
✅ Customizable Appearance – Change bar colors, text, and animations.
✅ Integration with Tab Bar Controller – Works well with UITabBarController
.
2. Creating a UINavigationController
You can create a UINavigationController
in two ways:
- Using Storyboard
- Programmatically
2.1 Using Storyboard
- Drag a
UINavigationController
from the Object Library into your storyboard. - Set its root view controller (e.g.,
MainViewController
). - Add additional view controllers for navigation.
- Use
pushViewController(_:animated:)
to navigate forward. - Use
popViewController(animated:)
to go back.
2.2 Creating UINavigationController Programmatically
import UIKit
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
title = "Home"
let button = UIButton(type: .system)
button.setTitle("Go to Details", for: .normal)
button.frame = CGRect(x: 100, y: 200, width: 200, height: 50)
button.addTarget(self, action: #selector(goToDetails), for: .touchUpInside)
view.addSubview(button)
}
@objc func goToDetails() {
let detailVC = DetailViewController()
navigationController?.pushViewController(detailVC, animated: true)
}
}
class DetailViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .lightGray
title = "Details"
}
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
let navController = UINavigationController(rootViewController: MainViewController())
window?.rootViewController = navController
window?.makeKeyAndVisible()
}
}
✅ This creates a basic UINavigationController with two screens.
3. Navigating Between View Controllers
3.1 Push a New View Controller
To navigate to a new screen:
let detailVC = DetailViewController()
navigationController?.pushViewController(detailVC, animated: true)
3.2 Pop Back to Previous View Controller
To go back to the previous screen:
navigationController?.popViewController(animated: true)
3.3 Pop to the Root View Controller
To return to the first screen:
navigationController?.popToRootViewController(animated: true)
✅ This is useful for resetting navigation to the home screen.
4. Customizing UINavigationBar
4.1 Changing the Navigation Bar Color
navigationController?.navigationBar.barTintColor = UIColor.systemBlue
4.2 Changing the Title Font & Color
let attributes = [NSAttributedString.Key.foregroundColor: UIColor.white,
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 18)]
navigationController?.navigationBar.titleTextAttributes = attributes
4.3 Hiding the Navigation Bar
navigationController?.setNavigationBarHidden(true, animated: true)
✅ Useful for fullscreen pages like login or onboarding screens.
5. Adding Custom Buttons to Navigation Bar
5.1 Adding a Right Bar Button
navigationItem.rightBarButtonItem = UIBarButtonItem(
title: "Edit",
style: .plain,
target: self,
action: #selector(editTapped)
)
@objc func editTapped() {
print("Edit button tapped!")
}
✅ This adds a button on the top right corner of the navigation bar.
6. Implementing a Back Button with Custom Action
By default, UINavigationController
provides a back button, but you can customize it:
navigationItem.leftBarButtonItem = UIBarButtonItem(
title: "Back",
style: .plain,
target: self,
action: #selector(backTapped)
)
@objc func backTapped() {
navigationController?.popViewController(animated: true)
}
✅ This allows custom handling when the back button is pressed.
7. Swipe to Go Back Gesture
The navigation controller includes a built-in swipe-to-go-back feature. You can enable or disable it:
navigationController?.interactivePopGestureRecognizer?.isEnabled = false
✅ Useful if you want to prevent accidental swiping in certain screens.
8. UINavigationController with UITabBarController
UINavigationController
can be used inside a UITabBarController
.
let homeVC = UINavigationController(rootViewController: HomeViewController())
let profileVC = UINavigationController(rootViewController: ProfileViewController())
let tabBarController = UITabBarController()
tabBarController.viewControllers = [homeVC, profileVC]
✅ Each tab now has its own navigation stack.
9. Example: Full UINavigationController Implementation
import UIKit
class HomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
title = "Home"
let button = UIButton(type: .system)
button.setTitle("Go to Profile", for: .normal)
button.frame = CGRect(x: 100, y: 200, width: 200, height: 50)
button.addTarget(self, action: #selector(goToProfile), for: .touchUpInside)
view.addSubview(button)
}
@objc func goToProfile() {
let profileVC = ProfileViewController()
navigationController?.pushViewController(profileVC, animated: true)
}
}
class ProfileViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .lightGray
title = "Profile"
navigationItem.rightBarButtonItem = UIBarButtonItem(
title: "Settings",
style: .plain,
target: self,
action: #selector(goToSettings)
)
}
@objc func goToSettings() {
let settingsVC = SettingsViewController()
navigationController?.pushViewController(settingsVC, animated: true)
}
}
class SettingsViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
title = "Settings"
}
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
let navController = UINavigationController(rootViewController: HomeViewController())
window?.rootViewController = navController
window?.makeKeyAndVisible()
}
}
✅ This creates a UINavigationController with Home → Profile → Settings screens.
10. Summary
✔️ UINavigationController
manages hierarchical navigation with push and pop transitions.
✔️ Supports custom navigation bar styles, buttons, and gestures.
✔️ Works well with UITabBarController
for tab-based apps.
✔️ Provides back navigation and swipe gestures.
Would you like help with custom transitions or animations in UINavigationController? 🚀