I was having some problems with trying to run a mo...
# squarelibraries
s
I was having some problems with trying to run a molecule presenter on iOS with an EXC_BAD_ACCESS error. Perhaps similarly to this https://github.com/cashapp/molecule/issues/547 I am using
DisplayLinkClock
from molecule in the context of my coroutineScope running this presenter. I ended up having to use
Dispatchers.Main + DisplayLinkClock
as the
CoroutineContext
which is running the presenter to have the app not crash, but I am not sure if this is what I should be doing since then the entire persenter would be running on the main thread if I understand this correctly? Anyone who has tackled this in the past has any ideas here perhaps?
Well, on Android I suppose I am using
AndroidUiDispatcher.Main
on my presenters already. So from my understanding, doing
Dispatchers.Main
should be the equivalent on iOS, so this should be fine
c
Looking at my usage of Molecule in a KMP app (Android + iOS), I see that my implementation matches yours. Adding some snippets in a moment
Copy code
expect abstract class MoleculeViewModel() : ViewModel {
    val moleculeScope: CoroutineScope
}
Copy code
// iOS implementation
actual abstract class MoleculeViewModel : ViewModel() {
    actual val moleculeScope = CoroutineScope(
        viewModelScope.coroutineContext +
            Dispatchers.Main + // <- This prevents hangs on iOS. Without this, presenters collecting flows will happen immediately without a hop
            DisplayLinkClock
    )
}
Copy code
// Android implementation
actual abstract class MoleculeViewModel actual constructor() : ViewModel() {
    actual val moleculeScope: CoroutineScope = CoroutineScope(viewModelScope.coroutineContext + AndroidUiDispatcher.Main)
}
s
// <- This prevents hangs on iOS. Without this, presenters collecting flows will happen immediately without a hop
Surprised it even ran in the first place tbh because I am just getting a crash immediately before anything would be emitted from the presenter when I am missing it. But thanks a lot for sharing your snippets, then it sounds like I probably got the right idea then. Thanks a lot!
c
It is possible that the "hang" was actually the thing that Xcode does when an app crashes: pausing at the "breakpoint" in the stacktrace.
s
Ah yeah, then it must've been the same behavior we experienced
r
Thanks for the snippet @curioustechizen. I asked this over in #C3PQML5NU (https://kotlinlang.slack.com/archives/C3PQML5NU/p1775263858145339) and @Chrimaeon sent me here. thank you color Based on some advice from ole Claude I was able to consolidate the view model into
commonMain
and switch the
moleculeRecompositionMode
and
moleculeCoroutineContext
per platform.
s
Why would you not want
RecompositionMode.ContextClock
for the iOS target? Isn't the point of DisplayLink that it provides the necessary information inside the coroutine context so that you will actually get recompositions following that rather than just use the immediate alternative?
r
Good point. I believe I do want
RecompositionMode.ContextClock
for both ios and android.
s
What did you end up doing after all? 😄
r
I went with
RecompositionMode.ContextClock
on both Android and iOS. 🙂 It worked great 👍
✅ 1
c
I'm seeing some "refreshing" issues on iOS that might be related to
ContextClock
but I cannot tell for sure. My usecase is 1. I have a screen that upon entering starts collecting a flow. In the presenter this is in the
present
method as
LaunchedEffect(Unit) { startCollectingMyFlow() }
2. This screen has a button that when pressed, opens a bottom sheet (this is a navigation event) 3. When the bottom sheet is closed, looks like the flow doesn't "resume" collection immediately. I see some missed emissions I don't see this problem on Android so I'm guessing it might have to do with the recomposition mode or the molecule coroutine context. Edit: The problem exists on Android too. So this has nothing to do with molecule scope or recomposition mode.
Does this ring a bell to anyone here?
Also, is there a reason for the
moleculeCoroutineContext
on iOS to use
Dispatchers.Main
and not
Dispatchers.Main.immediate
?
s
Regarding 1. When a bottom sheet opens the screen in the background should still be in a non-destroyed state, so how come your presenter is not just working normally? What makes it stop presenting? Regarding .immediate I don't actually know what the difference is in iOS, but the answer may be that we need to use that there too blob shrug
c
Yes I just don't understand what's up with this flow. Looks like something more fundamental. Will dig deeper (it might even have to do with the flow emission and not the collection).
Update: This was an operator error. The bug was in the flow emission. Once I fixed that everything on the presenter end Just Works ™️
🦜 1
r
Update for me: I've decided to not use Molecule to expose state. I've found a simpler approach. More info: https://kotlinlang.slack.com/archives/C5HT9AL7Q/p1780244622720639?thread_ts=1775936064.005949&cid=C5HT9AL7Q