Hi guys, Little question, does Compose Navigation ...
# compose-ios
s
Hi guys, Little question, does Compose Navigation support params on iOS? I have been having issue with a really simple case where navigating between pages works well, but if I add a param, it just crash on iOS, but works like a charm on Android.
Copy code
compose = "1.6.11"
compose-plugin = "1.6.11"
navigationCompose = "2.7.0-alpha07"
Then here is the nav
Copy code
NavHost(
        navController = navController,
        startDestination = AutomedonScreen.Splash.name,
        modifier = Modifier.fillMaxSize()
    ) {
        composable(route = AutomedonScreen.Login.name) {
            LoginScreen(
                modifier = Modifier.padding(
                    bottom = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
                ).fillMaxSize(),
                context = context,
                nav = navController
            )
        }
        composable(route = AutomedonScreen.Splash.name) {
            SplashScreen(
                modifier = Modifier.fillMaxSize(),
                context = context,
                nav = navController
            )
        }
        composable(route = "${AutomedonScreen.Geolocation.name}/{routeTo}") { backStackEntry ->
            GeolocationPermissionScreen(
                modifier = Modifier.padding(
                    top = WindowInsets.systemBars.asPaddingValues().calculateTopPadding(),
                    bottom = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
                ).fillMaxSize(),
                routeTo = backStackEntry.arguments?.getString("routeTo")
                    ?: AutomedonScreen.Login.name,
                context = context,
                nav = navController
            )
        }
From the Splash screen I am using this to navigate to Geolocation page, really simple:
Copy code
routeTo = AutomedonScreen.Login.name
        nav.navigate(AutomedonScreen.Geolocation.name + "/$routeTo")
that result in
Uncaught Kotlin exception: kotlin.IllegalArgumentException: No destination with route /Login is on the NavController's back stack. The current destination is Destination route=Geolocation/{routeTo}
Thanks…
r
You could go with 1.7.0-alpha01 that has the latest navigation lib and where you can use type safety. 🙂
i
Compose Navigation support params on iOS?
Yes
it just crash on iOS, but works like a charm on Android.
Please open an issue with simplified reproduction in our issue tracker, I'll have a look
No destination with route /Login is on the NavController's back stack.
It looks like "Geolocation" substring is missing. Can it be null or so in your code?
You could go with 1.7.0-alpha01 that has the latest navigation lib and where you can use type safety. 🙂
It does not related to question/problem. string params should work just fine in 1.6.11/2.7.*
s
Thanks @Richard but I want to keep a bit “stability” with 1.6.11 and I had a quick try yesterday and some component were missing. @Ivan Matkov Here is the tracking link https://youtrack.jetbrains.com/issue/CMP-5721/iOS-Crash-when-navigation-with-Parameters
It looks like “Geolocation” substring is missing. Can it be null or so in your code?
No, impossible, I keep my pages as enum and it is always available everywhere.
Copy code
enum class AutomedonScreen(val title: String) {
    Splash("Splash"),
    Login("Login"),
    Geolocation("Geolocation")
}
On android it really works fine, but on iOS, it can’t even find this enum within the nav.
Copy code
println("Geolocation/$routeTo") // this is printed correclty on iOS and routeTo is Automedon.Login.name (Login)
nav.navigate("Geolocation/$routeTo") // routeTo is Login and I have hardcoded Geolocation... still not working
Even if I hardcode the Geolocation I am still getting
No destination with route /Login is on the NavController's back stack. The current destination is Destination route=Geolocation/{routeTo}
Which is really weird. If I navigate to another page without param, it works fine even on iOS I will submit an issue
🙏 1
👀 1
i
Trying to recreate reproduction. What I had to change: • Automedon -> AutomedonScreen • Removed context arg • Removed suspend from navigateToGeolocation (cannot be called directly from init as shown) • Define test screens somehow And it works just fine on iOS. So I kindly ask to provide full but simple reproduction.
repro.kt
Simulator Screenshot - iPhone 15 - 2024-07-22 at 11.42.55.png
Let me re-check one more thing, but the point about full repro is still here
Well, nothing found/reproduced, but noticed that
Uncaught Kotlin exception: kotlin.IllegalArgumentException: No destination with route /Login is on the NavController's back stack. The current destination is Destination route=Geolocation/{routeTo}
The error is about transaction FROM
Geolocation/{routeTo}
, not from splash. And you're trying to navigation to "/Login" instead of just "Login" that you registered in graph. It's not listed in any provided code, so it's probably why it's not reproducible. Waiting for additional information from your side to continue investigation (if it's still needed)
s
Thanks a lot @Ivan Matkov for the check, then the reason might be totally something else, I thought the crash only happen from Splash… To give you more information, in my Geolocation page I have this.
Copy code
@Composable
fun GeolocationPermissionScreen(
    modifier: Modifier,
    routeTo: String,
    context: Any?,
    nav: NavHostController
) {

    val viewModel: GeolocationPermissionViewModel =
        viewModel { GeolocationPermissionViewModel(context) }
    val navBackStackEntry =
        remember { nav.getBackStackEntry("${AutomedonScreen.Geolocation.name}/$routeTo") }

    LaunchedEffect(navBackStackEntry) {
        println("GeolocationPermissionScreen LaunchedEffect IOS")
        // Observer to detect when this entry is resumed
        val observer = LifecycleEventObserver { _, event ->
            if (event == Lifecycle.Event.ON_RESUME) {
                // Call the function when the screen is revisited
                viewModel.checkGeolocationPermission(nav, routeTo)
            }
        }
        // Add observer
        navBackStackEntry.lifecycle.addObserver(observer)
    }
If I comment the
LaunchedEffect
and the
navbackStackEntry
, it can navigate to that page. This piece of code works on Android, all I want to do is after the user is in the device app setting to modify the location permission, after returning to the app, I am checking the permission on the
ON_RESUME
. That part crash on iOS.
Copy code
val navBackStackEntry =
        remember { nav.getBackStackEntry("${AutomedonScreen.Geolocation.name}/$routeTo") }
The enum is not loaded here. Sorry I really thought it never load that page at first You can mark it as closed, sorry for the trouble…🙏
The enum is loaded in Android, but is empty in iOS. At least there is still a small issue here to report 😁