How do I get the RootViewController from a pushed controller?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
From a pushed controller, the root of the current navigation flow is usually the first controller in navigationController?.viewControllers. The catch is that this is the root of the navigation stack, not necessarily the application's outermost root view controller. That distinction matters in apps that use tab bars, scenes, modal containers, or multiple navigation stacks.
The Normal Case
From a pushed controller, the root of the current navigation stack is:
This works because viewControllers is the ordered stack managed by the navigation controller, and the first element is the root. If you only need the controller without casting, navigationController?.viewControllers.first is enough.
Navigation Root Versus Window Root
Many bugs come from calling both of these concepts "the root controller." They are not the same thing. In a tab-based app, the window root might be a UITabBarController, while the current navigation stack root is a screen inside the selected tab.
Use the navigation root when you want the base screen of the current push flow. Use the window root only when you actually need the outermost container.
Example With a Pushed Stack
Suppose the stack is HomeViewController, then DetailsViewController, then SettingsViewController. If code inside SettingsViewController needs the first controller in that stack, this is the normal pattern:
That code is correct for a push flow. It is not a general solution for every controller hierarchy in iOS.
Modal and Container Cases
If the current controller was presented modally, navigationController may be nil or may refer to a navigation controller embedded inside the modal itself. In those cases, presentingViewController or a container-specific reference may be more relevant than viewControllers.first.
This is why the wording of the original problem matters. "From a pushed controller" points to the navigation stack. "From any current controller in the app" is a different and much harder question.
Prefer Communication Patterns
Even though you can reach back to the stack root directly, doing so too often creates tight coupling. A pushed controller that constantly manipulates the root controller usually becomes harder to test and harder to reuse.
With that pattern, the pushed controller does not need to know whether the receiver is the root controller, a coordinator, or something else.
A Small Helper
If you need this often, wrap it in a helper:
That keeps the call sites short and makes the intent obvious.
Common Pitfalls
- Calling
navigationController?.viewControllers.firstfrom a controller that was presented modally. Fix: confirm the controller is actually inside the navigation stack you want. - Confusing the stack root with
view.window?.rootViewController. Fix: decide whether you need the current navigation root or the outer app container. - Force-casting the result with
as!. Fix: use safe casts because stack composition changes over time. - Reaching back to the root controller for business logic from deep screens. Fix: prefer delegates, coordinators, or shared state when the communication is architectural rather than navigational.
Summary
- From a pushed controller, the usual answer is
navigationController?.viewControllers.first. - That value is the root of the current navigation stack, not necessarily the app window root.
- Modal and container-based flows may require different references.
- Safe casting is better than force-casting when retrieving a specific root controller type.
- Direct access works, but delegate or coordinator patterns are often cleaner long-term.
Related reading
- How do I get the SharedPreferences from a PreferenceActivity in Android?
- How do I handle ImeOptions' done button click?
- How do I hide a menu item in the actionbar?
- How do I hide the status bar in a Swift iOS app?
- How do I hide the status bar in a Swift iOS app?
- How do I implement an Objective-C singleton that is compatible with ARC?
- How do I import a Swift file from another Swift file?
- How do I inspect the view hierarchy in iOS?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack 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.