Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App freezing when using iOS #442

Closed
alfietapping opened this issue Aug 24, 2023 · 10 comments
Closed

App freezing when using iOS #442

alfietapping opened this issue Aug 24, 2023 · 10 comments

Comments

@alfietapping
Copy link

alfietapping commented Aug 24, 2023

dependency - org.kodein.di:kodein-di-framework-compose:7:20:1

Im injecting a ScreenModel from the Voyager library and all is working well when i run the app on Android, but if i try to run it on iOS i get a vague error from xcode which i suspect is around memory management and the app freezes

Exception	NSTaggedPointerString *	0x8000000105b9ffd5
self	@thin iosApp.iOSApp.Type	iosApp.iOSApp	

Heres my screen model

class HomeScreenModel(
    private val savedTeamRepository: SavedTeamRepository
) : CoreScreenModel<HomeState, HomeEvent, HomeEffect>(HomeState())

Im then using realm

class SavedTeamRepositoryImpl(
    private val realm: Realm
) : SavedTeamRepository {

    override suspend fun insert(savedTeam: SavedTeam) {
        val dbTeam = savedTeam.toDbModel()
        realm.write {
            copyToRealm(dbTeam)
        }
    }

    override suspend fun observeAll(): Flow<List<SavedTeam>> = flow {

        val savedTeamsFlow = realm.query<DbSavedTeam>().asFlow()

        savedTeamsFlow.collect { changes: ResultsChange<DbSavedTeam> ->

            emit(changes.list.map { it.toEntity() })
        }
    }
}

Providing deps

val dataModule = DI.Module(name = "dataModule") {
    bindSingleton { RealmConfiguration.create(schema = provideRealmSchemaObjects()) }
    bindSingleton { Realm.open(instance()) }
    bindProvider<SavedTeamRepository> { SavedTeamRepositoryImpl(instance()) }
}

val homeModule = DI.Module(name = "homeModule") {
    bindProvider {
        HomeScreenModel(instance())
    }
}

private fun provideRealmSchemaObjects() = setOf(
    DbSavedTeam::class,
    DbPlayer::class,
    DbOffset::class
)

Then eventually in my App composable

@Composable
fun App() = withDI(homeModule, dataModule) {

    Navigator(HomeContent) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.White)
        ) {
            AppContent(
                modifier = Modifier
                    .weight(1f)
                    .fillMaxWidth()
            ) {
                CurrentScreen()
            }

            BottomNavBar(modifier = Modifier)
        }
    }
}
@alfietapping
Copy link
Author

Also just to add this other error on xcode

Thread 1: signal SIGABRT

@schmidt9
Copy link

Having similar error when trying to start similar @Composable fun App() = withDI {...} from XCode. @romainbsl do you plan to support Compose Multiplatform for iOS?

(Thread 1: EXC_BAD_ACCESS (code=1, address=0x18)

Stacktrace excerpt

#0	0x00000001033dc8b8 in kfun:org.kodein.di.DI.Module.<get-_name>#internal at /Users/runner/work/Kodein/Kodein/kodein-di/src/commonMain/kotlin/org/kodein/di/DI.kt:592
#1	0x00000001033dc9f4 in kfun:org.kodein.di.DI.Module#<get-name>(){}kotlin.String at /Users/runner/work/Kodein/Kodein/kodein-di/src/commonMain/kotlin/org/kodein/di/DI.kt:593
#2	0x00000001033f12c0 in kfun:org.kodein.di.internal.DIBuilderImpl#import(org.kodein.di.DI.Module;kotlin.Boolean){} at /Users/runner/work/Kodein/Kodein/kodein-di/src/commonMain/kotlin/org/kodein/di/internal/DIBuilderImpl.kt:278
#3	0x000000010340d230 in kfun:org.kodein.di.internal.DIBuilderImpl#import(org.kodein.di.DI.Module;kotlin.Boolean){}-trampoline at /Users/runner/work/Kodein/Kodein/kodein-di/src/commonMain/kotlin/org/kodein/di/internal/DIBuilderImpl.kt:277
#4	0x00000001033f1924 in <inlined-out:<anonymous>> [inlined] at /Users/runner/work/Kodein/Kodein/kodein-di/src/commonMain/kotlin/org/kodein/di/internal/DIBuilderImpl.kt:295
#5	0x00000001033f1914 in kfun:kotlin.collections#forEach__at__kotlin.Array<out|0:0>(kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Any?>} [inlined] at /opt/buildAgent/work/2fed3917837e7e79/kotlin/libraries/stdlib/common/src/generated/_Arrays.kt:13309
#6	0x00000001033f1914 in kfun:org.kodein.di.internal.DIBuilderImpl#importAll(kotlin.Array<out|org.kodein.di.DI.Module>...;kotlin.Boolean){} at /Users/runner/work/Kodein/Kodein/kodein-di/src/commonMain/kotlin/org/kodein/di/internal/DIBuilderImpl.kt:295
#7	0x0000000103407984 in kfun:org.kodein.di.DI.Builder#importAll(kotlin.Array<out|org.kodein.di.DI.Module>...;kotlin.Boolean){}-trampoline at /Users/runner/work/Kodein/Kodein/kodein-di/src/commonMain/kotlin/org/kodein/di/DI.kt:482
#8	0x00000001033dc660 in kfun:org.kodein.di.DI.Builder#importAll$default(kotlin.Array<out|org.kodein.di.DI.Module>...;kotlin.Boolean;kotlin.Int){} at /Users/runner/work/Kodein/Kodein/kodein-di/src/commonMain/kotlin/org/kodein/di/DI.kt:482
#9	0x00000001021f14f8 in kfun:di.di$lambda$0#internal at /Users/user/Documents/xcode/mingli_ios/projects/Mingli Font Viewer/composeApp/src/commonMain/kotlin/di/Kodein.kt:20
#10	0x00000001021f2120 in kfun:di.$di$lambda$0$FUNCTION_REFERENCE$0.invoke#internal at /Users/user/Documents/xcode/mingli_ios/projects/Mingli Font Viewer/composeApp/src/commonMain/kotlin/di/Kodein.kt:19
#11	0x00000001021f2198 in kfun:di.$di$lambda$0$FUNCTION_REFERENCE$0.$<bridge-UNNN>invoke(org.kodein.di.DI.MainBuilder){}#internal at /Users/user/Documents/xcode/mingli_ios/projects/Mingli Font Viewer/composeApp/src/commonMain/kotlin/di/Kodein.kt:19
#12	0x00000001024ddfdc in kfun:kotlin.Function1#invoke(1:0){}1:1-trampoline at /Users/admin/.gradle/daemon/8.2.1/[K][Suspend]Functions:1
#13	0x00000001033fb0f4 in kfun:kotlin#apply__at__0:0(kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Any?>}0:0 [inlined] at /opt/buildAgent/work/2fed3917837e7e79/kotlin/libraries/stdlib/src/kotlin/util/Standard.kt:83
#14	0x00000001033fb0d8 in kfun:org.kodein.di.internal.DIImpl.Companion.newBuilder#internal at /Users/runner/work/Kodein/Kodein/kodein-di/src/commonMain/kotlin/org/kodein/di/internal/DIImpl.kt:21
#15	0x00000001033fafc0 in kfun:org.kodein.di.internal.DIImpl#<init>(kotlin.Boolean;kotlin.Function1<org.kodein.di.DI.MainBuilder,kotlin.Unit>){} at /Users/runner/work/Kodein/Kodein/kodein-di/src/commonMain/kotlin/org/kodein/di/internal/DIImpl.kt:18
#16	0x00000001033dd590 in kfun:org.kodein.di.DI.Companion#invoke(kotlin.Boolean;kotlin.Function1<org.kodein.di.DI.MainBuilder,kotlin.Unit>){}org.kodein.di.DI at /Users/runner/work/Kodein/Kodein/kodein-di/src/commonMain/kotlin/org/kodein/di/DI.kt:626
#17	0x00000001033dd678 in kfun:org.kodein.di.DI.Companion#invoke$default(kotlin.Boolean;kotlin.Function1<org.kodein.di.DI.MainBuilder,kotlin.Unit>;kotlin.Int){}org.kodein.di.DI at /Users/runner/work/Kodein/Kodein/kodein-di/src/commonMain/kotlin/org/kodein/di/DI.kt:626
#18	0x00000001021f0fd0 in kfun:di.$init_global#internal at /Users/user/Documents/xcode/mingli_ios/projects/Mingli Font Viewer/composeApp/src/commonMain/kotlin/di/Kodein.kt:19
#19	0x0000000102552f48 in CallInitGlobalPossiblyLock ()
#20	0x00000001021f1144 in kfun:di#<get-di>(){}org.kodein.di.DI at /Users/user/Documents/xcode/mingli_ios/projects/Mingli Font Viewer/composeApp/src/commonMain/kotlin/di/Kodein.kt:1
#21	0x00000001021f7f64 in kfun:screen#App(androidx.compose.runtime.Composer?;kotlin.Int){} at /Users/user/Documents/xcode/mingli_ios/projects/Mingli Font Viewer/composeApp/src/commonMain/kotlin/screen/App.kt:12

@romainbsl
Copy link
Member

Hi, Actually I do use Kodein inside a Compose Multiplatform project, with Android and iOS.
I was not able to reproduce it.

Do you have a simple reproducer project ?

@romainbsl
Copy link
Member

@schmidt9 @alfietapping
Just retried on CMP and it's ok.
Do you do something special while creating your instances? like using coroutines or something?

Here is my (non) reproducer:
KMP-DI-REPRODUCER.zip

@schmidt9
Copy link

schmidt9 commented Apr 19, 2024

@romainbsl your reproducer works, so problem seems to be in other dependency (Voyager), trying to figure out with a separate reproducer

            voyagerVersion = "1.0.0"
...

            // https://voyager.adriel.cafe/setup
            implementation(libs.voyager.navigator)
            implementation(libs.voyager.transitions)
            implementation(libs.voyager.screenmodel)
            // https://voyager.adriel.cafe/screenmodel/kodein-integration
            implementation(libs.voyager.kodein)

@romainbsl
Copy link
Member

I also usse voyager with Kodein on a CMP project.
Given your context, can you try to reproduce it start from my project ?

@schmidt9
Copy link

Well I seem to find the cause (not obvious for me) - declaration order

import org.kodein.di.DI
import org.kodein.di.bindProvider

// declaration order matters:
// if you declare di (2) before homeScreenModule (1) crash occurs on both Android and iOS

// 1
val homeScreenModule = DI.Module(name = "homeScreen") {
    bindProvider {
        HomeScreenModel()
    }
}

// 2
val di = DI {
    importAll(
        homeScreenModule
    )
}

KodeinIOSTest.zip

@romainbsl
Copy link
Member

romainbsl commented Apr 19, 2024

Well... This looks normal to me.

if you do something like

val di = DI { import(myModule) }

val myModule = DI.Module("whatever") { ... }

Using val di = DI you are doing a direct assignement. Then DI { } DSL is executed. So it tries to import the module with a reference this is NOT yet created.

This is like doing a function:

fun do() {
  val a = b + 1 // b is unknown
  val b = 2
}

However, with Kodein you can still declare (2) before (1) by using a lazy property, like:

// 2
val di by DI.lazy {
    importAll(homeScreenModule)
}

// 1
val homeScreenModule = DI.Module(name = "homeScreen") {
    bindProvider {
        HomeScreenModel()
    }
}

There is no compiler issue, as the DI lambda could be lazy, but the compiler knows nothing about this.

@romainbsl
Copy link
Member

I closed the issue, but do not hesitate to reopen if needed.

@schmidt9
Copy link

thanks a lot for quick help, actually I'm not sure that @alfietapping has the same issue... but mine is solved

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants