https://kotlinlang.org logo
#compose-ios
Title
# compose-ios
d

Dan

03/12/2024, 3:30 PM
Hi there - I have a question about how to force a recompose, or redraw of the main
ComposeUiViewController
from iOS. I would like to trigger a redraw/recompose when the iOS app is opened by another app with a deeplink. Is there a way to do that? I have tried to use an
EnvironmentObject
to trigger a redraw but I’m a little lost.
c

Casey Brooks

03/12/2024, 3:36 PM
I don’t believe recomposition can be “forced” without a change to State. The idea of Compose is a “pure transformation” from State to UI, so if there are no changes to state, then the UI should be the exact same. If you’re reading values that are not backed by
State<T>
objects, you no longer have a “pure” UI and unexpected issues can arise. Forcing a recomposition without any change to state variables won’t have any effect on the UI. So if you want the UI to react to or display differently when opened via deepLinks, you should update a state variable with data from the deepLink. The UI then reads that state variable and responds appropriately when it changes as a result of the deepLink
d

Dan

03/12/2024, 3:39 PM
Thanks for the insight. So I need to find a way to pass a
State<T>
from the SwiftUI code into the
MainViewController
and then have the composable react accordingly
Unless I can capture iOS deeplinks directly in kotlin
c

Casey Brooks

03/12/2024, 3:46 PM
I’m not too familiar with Kotlin/Swift interop, or what the deepLink handling of iOS looks like, but I’d imagine you could just keep a top-level state property and directly update it from Swift code. Then the Compose UI reads from that state variable.
Copy code
//deepLinkHander.kt
val deepLinkUri = mutableStateOf<String?>(null)

@Composable
fun Application() { 
 	Text(deepLinkUri.value)   
}

//deepLinkHanderiOS.swift
onDeepLinkHandled { (uri) -> void in
   DeepLinkHander.deepLinkUri.setValue(uri)
}
d

Dan

03/12/2024, 3:48 PM
Looks promising - I’ll give it a go. Thanks again for your help
a

Albert Chang

03/13/2024, 2:29 AM
> I don’t believe recomposition can be “forced” without a change to State. There is a way actually. You can get the recompose scope by calling
currentRecomposeScope
in a composable function, and call
scope.invalidate()
elsewhere to force a recomposition.
d

Dan

03/13/2024, 8:18 AM
@Albert Chang thanks for the input. In the end I was able to pass state directly using a similar method outlined above by @Casey Brooks:
Copy code
// in Kotlin: DeepLinkHandler.kt
val deepLinkUri = MutableStateFlow<String?>(null)

// in Swift
func handleDeepLink(_ url: URL) {
    DeepLinkHandlerKt.deepLinkUri.tryEmit(value: url)
}
The interop works seamlessly 👍
7 Views