Skip to main content

Working with Navigation

1. Using UINavigationController

Property Value Description
viewControllers [UIViewController] Array of view controllers in the navigation stack
navigationBar UINavigationBar The navigation bar associated with the navigation controller
topViewController UIViewController? The top view controller in the navigation stack

Example: Pushing a View Controller

let newViewController = MyViewController()
navigationController?.pushViewController(newViewController, animated: true)

Example: Setting Navigation Title

navigationItem.title = "Home"

Example: Customizing Navigation Bar

navigationBar.backgroundColor = .systemBackground
navigationBar.tintColor = .systemBlue

2. Pushing and Popping View Controllers

Method Description Notes
pushViewController(_:animated:) Pushes a view controller onto the navigation stack Animated by default
popViewController(animated:) Pops the top view controller from the navigation stack Animated by default
popToViewController(_:animated:) Pops view controllers to a specific view controller Removes all view controllers above the target
popToRootViewController(animated:) Pops all view controllers to the root Clears entire navigation stack except root

Example: Pushing a View Controller

let newViewController = MyViewController()
navigationController?.pushViewController(newViewController, animated: true)

Example: Popping a View Controller

navigationController?.popViewController(animated: true)
Note: Navigation stack is managed by UINavigationController. Ensure view controllers are properly initialized before pushing.
Warning: Avoid pushing the same view controller multiple times to prevent stack bloat.

3. Customizing Navigation Bar

Property Value Description
navigationBar.prefersLargeTitles true / false Enables or disables large titles in the navigation bar.
navigationBar.backgroundColor UIColor Sets the background color of the navigation bar.
navigationBar.titleTextAttributes [NSAttributedString.Key: Any] Customizes the appearance of title text.
navigationBar.barTintColor UIColor Sets the background color of the navigation bar.
navigationBar.tintColor UIColor Sets the color of navigation bar items (buttons, text).

Example: Setting Navigation Bar Background Color

let navBar = UINavigationBar()
navBar.barTintColor = UIColor.systemBlue

Example: Customizing Title Text Attributes

let attributes: [NSAttributedString.Key: Any] = [
    .foregroundColor: UIColor.white,
    .font: UIFont.boldSystemFont(ofSize: 18)
]
navBar.titleTextAttributes = attributes
Note: Large titles require iOS 11 or later and must be enabled in the navigation controller's prefersLargeTitles property.

4. Using Navigation Bar Items

Item Type Description Usage
navigationBarItems Defines items to display in the navigation bar navigationBarItems(leading: ..., trailing: ...)
leading Items placed on the left side of the navigation bar navigationBarItems(leading: Button("Back") { ... })
trailing Items placed on the right side of the navigation bar navigationBarItems(trailing: Button("Save") { ... })

Example: Adding Navigation Bar Items

struct ContentView: View {
    var body: some View {
        NavigationView {
            Text("Main Content")
                .navigationBarItems(
                    leading: Button("Back") {
                        // Handle back action
                    },
                    trailing: Button("Save") {
                        // Handle save action
                    }
                )
        }
    }
}
Note: navigationBarItems is available in iOS 13 and later.

5. Implementing Custom Back Button

Property Description Usage
navigationBar.backItem Represents the back button item in the navigation bar. Used to customize the back button's title or image.
navigationBar.backIndicatorImage Custom image for the back indicator (arrow) in the navigation bar. Set to a custom image to replace default back arrow.
navigationBar.backIndicatorTransitionMaskImage Mask image used for the back indicator transition animation. Used to customize the animation of the back button.

Example: Custom Back Button Title

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Customize the back button title
        self.navigationItem.backBarButtonItem = UIBarButtonItem(
            title: "Back",
            style: .plain,
            target: nil,
            action: nil
        )
    }
}

Example: Custom Back Button Image

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set custom back indicator image
        let backImage = UIImage(named: "custom_back_arrow")
        self.navigationController?.navigationBar.backIndicatorImage = backImage
        self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = backImage
    }
}

6. Using Large Titles

Property Value Description
navigationController.navigationBar.prefersLargeTitles true Enables large titles in the navigation bar
navigationController.navigationBar.largeTitleDisplayMode automatic, always, never Controls when large titles are displayed

Example: Enabling Large Titles

override func viewDidLoad() {
    super.viewDidLoad()
    
    navigationController?.navigationBar.prefersLargeTitles = true
    navigationItem.largeTitleDisplayMode = .automatic
}
Note: Large titles are only supported in iOS 11 and later.

Key Points

  • Large titles provide a more spacious and visually appealing navigation bar
  • Requires setting prefersLargeTitles to true
  • Use largeTitleDisplayMode to control visibility

7. Hiding Navigation Bar

Property Value Description
isNavigationBarHidden false Boolean flag to control visibility of the navigation bar

Example: Hide Navigation Bar

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationController?.isNavigationBarHidden = true
    }
}

Example: Show Navigation Bar

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationController?.isNavigationBarHidden = false
    }
}
Note: Setting isNavigationBarHidden to true will hide the navigation bar, but it does not affect the status bar visibility.

8. Implementing Navigation Delegates

Delegate Method Description Return Value Notes
navigationController(_:willShow:animated:) Called before a view controller is displayed void Use to perform last-minute adjustments before presentation
navigationController(_:didShow:animated:) Called after a view controller is displayed void Use to trigger actions after view controller is fully visible
navigationController(_:willPopViewController:animated:) Called before popping a view controller from the stack Bool Return false to prevent popping
navigationController(_:didPopViewController:animated:) Called after popping a view controller from the stack void Use to clean up or update state after pop

Example: Implementing Navigation Delegate

class MyNavigationController: UINavigationController, UINavigationControllerDelegate {
    func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
        print("Will show view controller: \(viewController.title ?? "")")
    }
    
    func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
        print("Did show view controller: \(viewController.title ?? "")")
    }
}
Note: Set the delegate property of your navigation controller to an instance of your custom delegate class.

9. Using Segues in Storyboards

Segue Type Description Usage
Show Pushes a new view controller onto the navigation stack Used for hierarchical navigation
Present Modally Presents a view controller as a modal sheet For temporary or contextual interactions
Show Detail Replaces the detail view in a split view controller Used in iPad multitasking layouts

Example: Creating a Show Segue

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "ShowDetail" {
        let detailVC = segue.destination as! DetailViewController
        detailVC.item = selectedItem
    }
}
Note: Set the segue identifier in Interface Builder to match the prepare(for:sender:) check.
Warning: Avoid using performSegue(withIdentifier:sender:) without checking if the segue exists to prevent runtime crashes.

10. Passing Data Between View Controllers

Method Description Code Example
Segue Pass data using prepare(for:sender:) method
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destinationVC = segue.destination as? DetailViewController {
        destinationVC.data = self.data
    }
}
Direct Assignment Assign properties directly to the destination view controller
let detailVC = DetailViewController()
detailVC.data = self.data
navigationController?.pushViewController(detailVC, animated: true)
Closure Use closure to pass data back from child view controller
let detailVC = DetailViewController()
detailVC.onDataReceived = { data in
    self.receivedData = data
}

Example: Using Segue to Pass Data

class MasterViewController: UIViewController {
    var dataArray = ["Item 1", "Item 2", "Item 3"]
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let detailVC = segue.destination as? DetailViewController,
           let indexPath = tableView.indexPathForSelectedRow {
            detailVC.selectedItem = dataArray[indexPath.row]
        }
    }
}

Example: Using Closure for Data Return

class DetailViewController: UIViewController {
    var onDataReceived: ((String) -> Void)?
    
    @IBAction func saveButtonTapped(_ sender: UIButton) {
        onDataReceived?(textField.text ?? "")
        dismiss(animated: true)
    }
}

Was this article helpful?