Xcode crashed with SwiftUI preview and Koin?

Raymond Chan
2 min readOct 4, 2023

--

I encountered a crash in Xcode with Koin recently, when I tried to preview a SwiftUI component in Xcode, it kept crashing with the following error:

Thread 0 Crashed::  Dispatch queue: BSXPCCnx:com.apple.dt.xcode-previews.systemservices (BSCnx:client:com.apple.dt.uv.agent-preview-scene-service)
0 libsystem_kernel.dylib 0x1af2060cc __pthread_kill + 8
1 libsystem_pthread.dylib 0x1af25a1e8 pthread_kill + 256
2 libsystem_c.dylib 0x180129eb0 __abort + 124
3 libsystem_c.dylib 0x180129e34 abort + 136
4 shared 0x1060db608 konan::abort() + 12
5 shared 0x106108528 (anonymous namespace)::terminateWithUnhandledException(ObjHeader*)::$_1::operator()() const + 16
6 shared 0x106108340 void (anonymous namespace)::$_0::operator()<(anonymous namespace)::terminateWithUnhandledException(ObjHeader*)::$_1>((anonymous namespace)::terminateWithUnhandledException(ObjHeader*)::$_1) + 80
7 shared 0x106108050 (anonymous namespace)::terminateWithUnhandledException(ObjHeader*) + 12
8 shared 0x10610800c (anonymous namespace)::processUnhandledException(ObjHeader*) + 64
9 shared 0x10611c710 kotlin::ProcessUnhandledException(ObjHeader*) + 188
10 shared 0x10611f288 Kotlin_ObjCExport_trapOnUndeclaredException + 36
11 shared 0x1060cefc8 objc2kotlin_kfun:com.pfp.app.di#initKoin3(){} + 200 (/<compiler-generated>:1)
12 SplashScreen.1.preview-thunk.dylib 0x11041cde0 static AScreen_Previews.__preview__previews.getter + 64 (SplashScreen.swift:50)
13 iosApp 0x1026f3378 protocol witness for static PreviewProvider.previews.getter in conformance AScreen_Previews + 12
14 SwiftUI 0x10ba49e68 0x10b0ec000 + 9821800
15 iosApp 0x1026f33bc protocol witness for static _PreviewProvider._previews.getter in conformance AScreen_Previews + 40

After some trial-and-error, I figured out that Koin was initialized two times due to how it was written.

First, there were two classes that extend the AppObservable interface:

  • PreviewAppObservable — The class that generate SwiftUI preview.
  • DefaultAppObservable — The main class when the app is executed.

The problem was that Koin’s initialization was done in DefaultAppObservable and also PreviewAppObservable , this was the root cause of the crash — Koin was initialized two times! That was not something I expected… 🤯

PreviewAppObservable:

class PreviewAppObservable: AppObservable {
required init(savedState: ParcelableParcelableContainer? = nil) {
KoinHelper.doInitKoin()
//...
}
}

DefaultAppObservable

class DefaultAppObservable: AppObservable {
required init(savedState: ParcelableParcelableContainer? = nil) {
KoinHelper.doInitKoin()
//...
}
}

The solution is to remove the doInit() call in both PreviewAppObservable and DefaultAppObservable, moving KoinHelper.doInitKoin() to App class and done!

struct iOSApp: App {
init() {
KoinHelper.doInitKoin()
}
}

--

--