D-KMP sample now leverages iOS 16 navigation

Daniele Baroncelli
2 min readFeb 20, 2023

Navigation is processed in the shared-code, but binds to the iOS NavigationStack path

The D-KMP sample was first released in early 2021, following the D-KMP architecture concept, where both ViewModel and DataLayer are written as Kotlin Multiplatform shared-code, and the UI layer is implemented using Declarative UI frameworks (Compose and SwiftUI).

One of the main features of the D-KMP sample is the navigation being defined in the shared-code, with the support for multiple vertical backstacks, which work out of the box on any platform (the vertical backstack can be enabled/disabled for a specific root screen, with a simple flag).

D-KMP Navigation on SwiftUI

Until now, advanced navigation on iOS has been problematic, because SwiftUI had very inflexible navigation patterns, requiring hacks to achieve any customization.

Finally in SwiftUI 4.0 (iOS 16), Apple has come up with brand new navigation patterns (NavigationStack for iPhone and NavigationSplitView for iPad), which provide more flexibility.

The latest D-KMP sample is now leveraging the new iOS 16 navigation patterns, which fixed several navigation issues and made the code a lot cleaner.

Multiple vertical backstacks are achieved with the implementation of multiple NavigationStack, each of them binded to a different NavigationPath, whose value comes from the shared-code.

The UI states are remembered by placing all NavigationStacks under a ZStack, where only the active one is visible (opacity=1). The caching of the data states is instead managed in the shared-code.

D-KMP Navigation on Compose

The D-KMP sample runs Compose Multiplatform. For this reason, it’s not using Jetpack Navigation, which only works on Android’s Jetpack Compose, but a navigation implementation that works on any platform.

The navigation pattern is pretty simple. The “Router” composable “remembers” the navigation state, whose value comes from the shared-code, similarly to how it happens for iOS.

Each navigation function changes the navigation state, triggering a recomposition of the UI layer, which then presents the new destination screen.

The UI state of the screens in the multiple vertical backstacks are remembered using the “rememberSaveableStateHolder()” Compose function. As for iOS, the caching of the data states is managed in the shared-code.


The full D-KMP sample is available on GitHub:



Daniele Baroncelli

Mobile architect (client/server), with over 15 years experience. Focusing on Android, iOS, Kotlin, Golang, Compose, SwiftUI, KMP, MVI.