Thomas S.
03/26/2026, 8:59 AMScreenOrientationManager) that requires native iOS elements (callbacks, native views). Because of this, I declare it dynamically at runtime using the classic DSL in my iosMain. However, the Koin compiler fails the build of my commonMain because it can't find this definition during its compile-time checks.
/***/***/shared/src/commonMain/kotlin/*/*/*/shared/ui/App.kt:52:36 [Koin] Missing definition: *.*.*.*.ScreenOrientationManager
My iOS setup (iosMain):
val platformModule = module {
single<NativeViewProvider> { nativeViewProvider }
single<ScreenOrientationListener> { ScreenOrientationListener(onOrientationChanged) }
single<ScreenOrientationManager> { ScreenOrientationManagerIos(screenOrientationListener = get()) }
}
startKoin(platformModule = platformModule, isDebug = Platform.isDebugBinary)
My shared setup (commonMain):
@KoinApplication(modules = [SharedKoinModule::class])
internal class KoinApp
internal fun startKoin(
platformModule: Module,
isDebug: Boolean,
) {
startKoin<KoinApp> {
modules(platformModule)
}
// ...
}
@Module
@ComponentScan("*.*.*.shared")
internal class SharedKoinModule
The injection point that crashes the compiler (App.kt in commonMain):
val screenOrientationManager: ScreenOrientationManager = koinInject()
It seems the Koin compiler (compile-time safety) completely ignores my platformModule injected at runtime, which causes the @KoinApplication check to fail. What is the best practice in 4.2.x to inject dependencies that are tightly coupled to the native UI (runtime) without triggering the [Koin] Missing definition error from the Compiler Plugin?
Thanks in advance for your help!Thomas S.
03/26/2026, 9:03 AMCoreKoinModule in commonMain, CoreKoinModule.ios in iosMain, etc.tezov
03/26/2026, 12:52 PMThomas S.
03/26/2026, 3:49 PMThomas S.
03/26/2026, 4:20 PM@Single definition on the iOS side just so the KSP compiler plugin can "see" that a `ScreenOrientationManager`is provided during compile-time:
@Single
internal fun ScreenOrientationManager(): ScreenOrientationManager = ScreenOrientationManagerIos(
ScreenOrientationListener {}
)
And I kept my runtime DSL module exactly as it was:
val platformModule = module {
single<NativeViewProvider> { nativeViewProvider }
single<ScreenOrientationListener> { ScreenOrientationListener(onOrientationChanged) }
single<ScreenOrientationManager> { ScreenOrientationManagerIos(screenOrientationListener = get()) }
}
startKoin(platformModule = platformModule, isDebug = Platform.isDebugBinary)
At runtime, the DSL definition overrides the dummy annotated one, so the correct instance is used.
Does anyone have a cleaner solution to properly include a runtime platformModule in the compiler plugin checks without resorting to dummy definitions? I'd love to hear your thoughts!tezov
03/28/2026, 8:18 AMkoinCompiler {
// userLogs = true
// debugLogs = true
compileSafety = false
// unsafeDslChecks = false
}tezov
03/28/2026, 8:19 AMThomas S.
04/10/2026, 5:12 PM@Single
internal fun screenOrientationManager(
@Provided screenOrientationListener: ScreenOrientationListener
): ScreenOrientationManager = ScreenOrientationManagerIos(
screenOrientationListener = screenOrientationListener
)
Thanks to @arnaud.giuliani for the solution in your Droidcon presentation.arnaud.giuliani
04/13/2026, 2:49 PM