Skip to content

How to Fix iOS Navigation Controller Push Error

DodaTech Updated 2026-06-24 3 min read

In this tutorial, you'll learn about How to Fix iOS Navigation Controller Push Error. We cover key concepts, practical examples, and best practices.

The Problem

You call pushViewController and get:

Attempt to push a view controller that is already on the navigation stack

Or:

Finishing up a navigation transition in an unexpected state

Or the back button disappears after pushing a view controller.

Quick Fix

Step 1: Check if a navigation controller exists

// Ensure the current view controller is inside a navigation stack
guard let navController = self.navigationController else {
    print("No navigation controller")
    return
}
navController.pushViewController(detailVC, animated: true)

If navigationController is nil, the view controller was not embedded in a UINavigationController.

Step 2: Prevent double-push on the same instance

// Wrong - pushing the same instance twice
let vc = DetailViewController()
navigationController?.pushViewController(vc, animated: true)
navigationController?.pushViewController(vc, animated: true) // crash

// Right - create a new instance each time
navigationController?.pushViewController(DetailViewController(), animated: true)

Step 3: Use present instead of push for modals

// For standalone flows that are not part of the navigation hierarchy
present(detailVC, animated: true, completion: nil)

Use dismiss(animated:) to return from a presented view controller.

Step 4: Avoid pushing during transitions

// Delay the push until the current transition ends
navigationController?.pushViewController(detailVC, animated: false)

If you need to push immediately after another navigation action, use a short delay:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
    self.navigationController?.pushViewController(detailVC, animated: true)
}

Step 5: Check the storyboard segue

If using segues, ensure the segue type is Show (e.g. Push) and not Present Modally:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showDetail" {
        let destVC = segue.destination as! DetailViewController
        destVC.item = selectedItem
    }
}

Step 6: Use setViewControllers for stack management

// Replace the entire navigation stack
navigationController?.setViewControllers([rootVC, detailVC], animated: true)

This is useful for login flows where the back button should not return to the login screen.

Step 7: Handle the case where navigation bar is hidden

navigationController?.setNavigationBarHidden(false, animated: true)

A hidden navigation bar prevents the back button from appearing.

Prevention

  • Always check navigationController is not nil before pushing.
  • Create new view controller instances per push navigation event.
  • Avoid pushing while the navigation controller is still animating.

Common Mistakes with navigation controller

  1. Misunderstanding that String is [Char] with poor performance for large text operations
  2. Using foldl instead of foldl' causing stack overflow on large lists
  3. Forgetting deriving (Show, Eq) on custom data types needed for debugging

These mistakes appear frequently in real-world IOS code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### What does "Finishing up a navigation transition in an unexpected state" mean?

You attempted a push or pop while the navigation controller was still animating the previous transition. Use animated: false or add a delay.

How do I remove a view controller from the stack?

Use navigationController?.popViewController(animated:) or navigationController?.viewControllers.remove(at:).

Why does the back button disappear?

The navigation bar is hidden, or the pushed view controller overrides navigationItem.hidesBackButton. Check both settings.

DodaTech Tool Reference

Doda Browser's Navigation Flow tool visualizes the current navigation stack of any running iOS app, helping developers debug push/pop state issues.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro