John O'Reilly
03/30/2026, 8:57 AM2.4.0-dev-7255 successfully but getting following in 8268 for example
Could not find or use auto-linked library 'KotlinCoroutineSupport': library 'KotlinCoroutineSupport' not found
Undefined symbol: (extension in Shared):ExportedKotlinPackages.dev.johnoreilly.chip8.Emulator.screen.getter : any KotlinCoroutineSupport.KotlinTypedStateFlow<Self.Swift.AsyncSequence.Element == (extension in Shared):ExportedKotlinPackages.dev.johnoreilly.chip8.Screen>
Undefined symbol: nominal type descriptor for KotlinCoroutineSupport.KotlinTypedFlowIterator
Undefined symbol: protocol conformance descriptor for KotlinCoroutineSupport.KotlinTypedFlowIterator<A> : Swift.AsyncIteratorProtocol in KotlinCoroutineSupportArtem Olkov
03/30/2026, 9:19 AMgradlew clean and cleaning the derived data of xcode?John O'Reilly
03/30/2026, 9:27 AMArtem Olkov
03/30/2026, 9:27 AMArtem Olkov
03/30/2026, 9:39 AMArtem Olkov
03/30/2026, 9:40 AMJohn O'Reilly
03/30/2026, 9:47 AMJohn O'Reilly
03/30/2026, 9:47 AMArtem Olkov
03/30/2026, 9:51 AM.asAsyncSequence . We can do a shorthand for SharedFlow and all who inherit from it - and provide AsyncSequence conformance out of the box. But for that we would love to hear user feedback - if there is enough requests than we will break consistency and we will provide a difference in behaviours. but by default we think that consistency in the resulted API and usages of that API is more important.John O'Reilly
03/30/2026, 12:24 PMObserving (https://skie.touchlab.co/features/flows-in-swiftui#observing-swiftui-view) ......but can easily enough replace that with for await etc (as @russhwolf for example did here https://github.com/russhwolf/To-Do/commit/0f6e543bb66e4acd359859dcce18d0320de582b0)Artem Olkov
03/30/2026, 12:28 PMfor try await toDos in repository.getList().asAsyncSequence() { ?John O'Reilly
03/30/2026, 12:30 PMdorche
03/30/2026, 5:02 PMtoStruct() call a concept required to get SwiftUI to work/be performant? I'd like to not have to recreate my models in Swift but unsure if that would introduce other problems... I assume we can't get automatic conversion of data classes to structs with swift export as it might not be desirable in all cases? Perhaps behind a flag?Dmitry Stakhov
03/30/2026, 5:41 PMdorche
03/30/2026, 6:04 PMArtem Olkov
03/30/2026, 6:30 PMtoStruct() call a concept required to get SwiftUI to work
I'm not sure I understand what do you mean.
1. "to work" part - please consult this repo as an example of SwiftUI working with ref types. Or this. Or the two that were mentioned in this thread before - all of them uses Swift Export with SwiftUI.
2. "be performant" part - Can you please elaborate, why usage of reference type would affect performance of SwiftUI?dorche
03/30/2026, 7:34 PMswift-export-sample makes it a bit clearer, UsersDetailView directly uses Shared.User which is closer to what most people will want to do.
re the "be performant" part - I am not sure how SwiftUI looks under the hood and whether reference types are a problem, this was purely a guess - if it works similarly to Compose, it's very rare that you'd want referential equality checks, which would explain the usage of structs in pure Swift code.
Also (this should probably be a separate thread) none of these samples show the most common use case - the ViewModel having a sealed class/interface that models the whole screen state, i.e. Loading, Error, Success with data. I think if we had such a sample available it would make things a bit more obvious and also I think it would reveal the need for something similar to SKIE's Observing like John has mentioned.Artem Olkov
03/31/2026, 9:55 AMsealed class/interface that models the whole screen state
That is correct - exhaustive sealed hierarchies are not fully supported yet. Feel free to follow https://youtrack.jetbrains.com/issue/KT-80000 for the progress.russhwolf
03/31/2026, 10:26 PMAsyncSequence conformance is not possible for flow Flow but is possible for SharedFlow et al? I'm curious to understand the correctness issue more.Artem Olkov
04/07/2026, 7:22 AMpublic val myPublicFlow = flow {
try {
emit('x')
} finally {
withContext(NonCancellable) {
delay(100.milliseconds)
println("Flow finished cancelling")
}
}
}
and a usage
public fun activateKotlin() {
val job = GlobalScope.launch(start = CoroutineStart.UNDISPATCHED) {
try {
myPublicFlow.collect {
awaitCancellation()
}
} catch (_: Throwable) {
}
println("Job is cancelled")
}
job.cancel()
}
This will produce
Flow finished cancelling
Job is cancelled
If we call that input from Swift
@MainActor
func activate() async {
let t = Task {
for await _ in myPublicFlow {
while (Task.isCancelled != false) {} // immitates awaitCancellation
}
print("Job is cancelled")
}
t.cancel()
}
We will get
Job is cancelled
Flow finished cancelling
This is not OK in general case. Behaviour becomes identical if we change the input with the following addition:
.shareIn(
GlobalScope,
started = Lazily, // doesn't matter
)
There are couple of more puzzlers that were demonstrated to us by the coroutines library team, but the main idea is visible - it's not OK to silently create a global dispatcher, that's not a trivial operation and the presence of such an operation should be visible to the end user. asAsyncSequence is a place for us to customise that operation in the future and to highlight to the user that there is nothing trivial going on here.