Need a piece of advice, I was writing a repository...
# multiplatform
a
Need a piece of advice, I was writing a repository in
commonMain
using coroutines. Normally, the methods in android would be marked by
suspend
and then they can fetch any data from remote or local. Also writing tests to this on JVM (Android in my case) is easy as we can create a
runBlocking
and assert the results. But when it comes to iOS we don't have any
suspend
methods and thus the same function cannot be tested and thus we end up adding a high order function which will give you an
onSuccess
or
onFailure
when
launch
coroutine gives result. This seems to be a bit messy to me because in common we end up maintaining 2 implementations for fetching same data each for android and iOS. (common is not "common" anymore in this case) I need an approach which can be directly exposed to both worlds with unit tests also working on both sides. How you guys create repositories and unit test them? Advices and approaches would be appreciated 🙂
âž• 1
e
i would also love a solution for this. we currently have an iOS fun with a callback that delegates to the suspend fun
it’s super clunky
k
For using suspend functions in iOS, you could check KotlinConf's CFlow. I also wrote about it here.
For unit tests, you can create common tests with coroutines
j
There will be methods generated with callback for suspend calls in 1.4 for Objective-C https://github.com/JetBrains/kotlin-native/issues/1684#issuecomment-612922865 So then you only need to test one version in common tests.
e
oh damn, nice!
k
Yeah waiting on that as well! But for now, making it work with what we have~
o
@edenman could you elaborate on how you delegate the callback function to the suspending one? Going from calback to suspend is easy with suspendCoroutine {}, but Im not sure how one would bridge going from suspend to callback.
e
Copy code
fun fooWithCallback(callback: (MyObject) -> Unit) {
  scope.launch { 
    val result = foo()
    callback(result)
  }
}
o
I see, what would the
scope
be? (Lets say this method is in a UserRepository)
Would it be a
MainScope
?
e
to be 100% honest we haven’t actually implemented the iOS side of this yet. for right now it’s just a
CoroutineScope(Dispatcher)
where Dispatcher is a
CoroutineDispatcher
and it does
Copy code
dispatch_async(queue) {
      block.run()
    }
o
How is that different from simply using Dispatchers.Main?
e
probably isn’t, we just do an expect/actual on
Dispatcher
so each platform can kick off stuff how they want
(i didn’t write this code, thinking maybe the person writing it didn’t know about Dispatchers.Main)
o
It might as well be different actually, I'm no coroutine expert either.
How do you guys hande Flow on iOS?
e
we don’t 😞
waiting for 1.4-M2 before we actively dive in the iOS side
i’ve just been forging ahead assuming we’ll be able to use all the stuff i’ve been building in kmp
o
Is there any other way you guys share reactiveness in kmp for ios if Flow not used?
e
nope, the plan is definitely to use Flow