Push Presentation is a navigation pattern in mobile applications where each new screen is added to the navigation stack on top of the previous one. The user can sequentially move forward through content and go back using the system button or swipe. According to Apple Developer, 2025, UINavigationController is used in 85% of iOS apps as the primary navigation pattern. In Android, similar functionality is implemented through FragmentManager and NavController from the Navigation Component.
Key Takeaways
Push Presentation is a navigation mechanism where each new screen is placed on top of the stack, while the previous screen remains in memory underneath. The user delves deeper into content by sequentially opening detail screens, and the back button returns them to the previous step.
The architecture of Push navigation is based on the LIFO (Last In, First Out) data structure. A new screen is always added to the end of the stack, and removal occurs only from the top. This guarantees predictable behavior: the user always knows that the back button will take them exactly one step back. The navigation stack can contain from 2 to 10+ screens depending on the application complexity.
Push Presentation is the primary pattern in applications with hierarchical content: news feeds, product catalogs, multi-level menus, and documentation. According to Material Design, stack navigation is suitable for scenarios where the user explores content from general to specific, and each subsequent screen deepens the understanding of the topic.
The navigation stack is an ordered set of screens where each element stores the state of its ViewController or Fragment. During a Push operation, a new screen is added to the stack, its appearance is animated (slide from the right in iOS, slide from the bottom or Fade in Android), and it becomes active.
During a Pop operation (pressing back), the top screen is removed from the stack, destroyed or moved to memory, and the previous screen becomes active. iOS by default destroys the popped ViewController, freeing memory. Android can save the Fragment in the back stack with the ability to restore it without recreation.
Stack depth affects performance: each screen in the stack consumes memory. It is recommended not to keep more than 10 screens in the stack. For deep navigation, use PopToRoot or restart the stack with a new root screen. Navigation Component in Android automatically manages the stack state via SavedStateHandle.
UINavigationController is an iOS container controller that manages a stack of UIViewControllers. It automatically displays a navigation bar with the current screen title and a back button. The default push animation is a slide from right to left, creating a sense of immersion in the content for the user.
Adding a screen is done via pushViewController(_:animated:). Removal is done via popViewController(animated:). To return to the root screen, use popToRootViewController(animated:). UINavigationController also supports programmatic stack management through the viewControllers property — an array of all controllers in the stack.
The navigation bar contains the screen title, a back button, and optional action buttons. Starting with iOS 11, Large Titles (prefersLargeTitles) allow displaying the title in an enlarged font that animates and shrinks during scrolling. This improves the navigation hierarchy and informs the user about the current section.
let detailVC = DetailViewController()
detailVC.title = "Item Details"
navigationController?.pushViewController(detailVC, animated: true)
// Pop to previous screen
navigationController?.popViewController(animated: true)
// Pop to root
navigationController?.popToRootViewController(animated: true)
Navigation Component is an Android Jetpack library for declarative navigation. It provides NavController, which manages fragments or compose screens through a navigation graph (nav_graph). Push in Android is similar to iOS: each new Fragment is added to the back stack, and the back button returns to the previous one.
NavHost is a container that displays the current destination from the NavGraph. NavGraph is an XML file describing all application screens and connections between them. Transitions are defined through actions specifying the destination and optional arguments. Navigation Component automatically handles system back, animations, and state preservation.
For passing data between screens, Navigation Component supports Safe Args — code generation of type-safe argument classes. Instead of manually placing data into a Bundle, the developer declares arguments in the NavGraph and receives them through generated Directions and Args classes. Safe Args eliminates type mismatch errors and simplifies refactoring.
// NavGraph definition in XML
<!-- res/navigation/nav_graph.xml -->
@navigation {
NavHost(startDestination = "list") {
composable("list") { ListScreen() }
composable(
"detail/{itemId}",
arguments = listOf(navArgument("itemId") { type = NavType.IntType })
) { DetailScreen(it.arguments()?.getInt("itemId") ?: 0) }
}
}
// Navigate programmatically
navController.navigate("detail/42")
Combining Bottom Navigation and Push navigation is a common pattern in mobile applications. Each Bottom Navigation tab has its own screen stack. Navigation Component supports this through NavHost per tab or a single NavHost with separate graphs for each tab. Switching tabs does not reset the push stack state.
Push Presentation and Modal Presentation solve different navigation tasks. Push is designed for sequential content viewing, where each new screen deepens the context. Modal is for focused tasks that require completion. In practice, it is important to choose the right pattern for a specific scenario.
The main selection criteria: if the user should be able to freely go back without losing context — choose Push. If the task is temporary and blocks the main content (form, authorization) — use Modal. Mixing patterns on one screen (Push inside Modal) is acceptable but requires a clear visual hierarchy.
A common mistake is using Modal for sequences of screens that are logically part of the main flow. For example, an order creation wizard (Step 1 → Step 2 → Step 3) is better implemented via Push inside a modal container rather than through a chain of modal windows. This preserves the navigation hierarchy and predictability of return.
Let us examine a complete implementation of Push navigation on both platforms. The Swift example demonstrates UINavigationController with programmatic stack management and deep link handling. The Kotlin example shows Navigation Component with NavHost, arguments, and animations.
class ListViewController: UIViewController {
func showDetail(_ itemId: Int) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let detailVC = storyboard.instantiateViewController(
withIdentifier: "DetailViewController"
) as! DetailViewController
detailVC.itemId = itemId
navigationController?.pushViewController(detailVC, animated: true)
}
}
class DetailViewController: UIViewController {
var itemId: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
title = "Item #\(itemId)"
}
}
@Composable
fun PushNavigationApp() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "list") {
composable("list") {
ListScreen(
onItemClick = { id -> navController.navigate("detail/$id") }
)
}
composable(
"detail/{itemId}",
arguments = listOf(navArgument("itemId") { type = NavType.IntType })
) { backStackEntry ->
val itemId = backStackEntry.arguments()?.getInt("itemId") ?: 0
DetailScreen(itemId = itemId, onBack = { navController.popBackStack() })
}
}
}
The examples demonstrate basic Push navigation: list → details. iOS uses storyboards and UINavigationController with manual data passing. Android uses NavHost with type-safe arguments and automatic back stack management. Both approaches support deep links, custom animations, and state preservation on rotation.
Frequently Asked Questions
Push adds a screen to the UINavigationController stack with a back button. Present opens a modal window without a back button — the user must explicitly close it. Push is suitable for sequential content, Present is for focused tasks. In SwiftUI, Push corresponds to NavigationLink, and Present corresponds to .sheet.
Navigation Component provides popBackStack methods to a specific point and popUpTo for stack clearing. To prevent stack overflow, use popUpTo(startDestination) { inclusive = true } before navigate. This ensures the stack contains no more than 5–7 screens simultaneously.
Yes, combining Push and Modal is a standard pattern. For example, list → Push to details → Modal for authorization. It is recommended not to nest Push inside Modal: a modal window should not contain stack navigation. If a sequence of screens is needed inside a modal window, use Push inside a modal container.
Deep Links in Push navigation open the app on a specific screen. iOS uses URL schemes and Universal Links with UINavigationController. Android uses Intent Filters with NavDeepLink. In both cases, the system parses the link and creates a navigation stack to the target screen, preserving the ability to go back.
iOS uses the standard slide animation, which is customizable through UINavigationControllerDelegate. Android Navigation Component supports custom animations via XML resources (slide_in_right, slide_out_left). For Compose, use AnimatedNavHost with the animateItemPlacement modifier.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also