diff --git a/Fruitties/iosApp/iosApp/IOSViewModelStoreOwner.swift b/Fruitties/iosApp/iosApp/IOSViewModelStoreOwner.swift index b7e9047..c992f8c 100644 --- a/Fruitties/iosApp/iosApp/IOSViewModelStoreOwner.swift +++ b/Fruitties/iosApp/iosApp/IOSViewModelStoreOwner.swift @@ -1,21 +1,19 @@ import SwiftUI import shared -/// A ViewModelStoreOwner specifically for iOS. -/// This is used with from iOS with Kotlin Multiplatform (KMP). -class IOSViewModelStoreOwner: ObservableObject, SwiftViewModelStoreOwner { +/// A ViewModelStoreOwner specifically for iOS to be an ObservableObject. +class IOSViewModelStoreOwner: ObservableObject, ViewModelStoreOwner { - var viewModelStore: Lifecycle_viewmodelViewModelStore = - Lifecycle_viewmodelViewModelStore() + var viewModelStore = ViewModelStore() /// This function allows retrieving the androidx ViewModel from the store. - func viewModel( + func viewModel( key: String? = nil, - factory: Lifecycle_viewmodelViewModelProviderFactory, - extras: Lifecycle_viewmodelCreationExtras? = nil + factory: ViewModelProviderFactory, + extras: CreationExtras? = nil ) -> T { do { - return try viewModelStore.getViewModel( + return try viewModel( modelClass: T.self, factory: factory, key: key, @@ -26,7 +24,13 @@ class IOSViewModelStoreOwner: ObservableObject, SwiftViewModelStoreOwner { } } + /// This can be called from outside when using the `ViewModelStoreOwnerProvider` func clear() { viewModelStore.clear() } + + /// This is called when this class is used as a `@StateObject` + deinit { + viewModelStore.clear() + } } diff --git a/Fruitties/iosApp/iosApp/ui/CartView.swift b/Fruitties/iosApp/iosApp/ui/CartView.swift index fc78eff..35f7d2b 100644 --- a/Fruitties/iosApp/iosApp/ui/CartView.swift +++ b/Fruitties/iosApp/iosApp/ui/CartView.swift @@ -20,7 +20,7 @@ import shared struct CartView: View { /// Injects the `IOSViewModelStoreOwner` from the environment, which manages the lifecycle of `ViewModel` instances. - @EnvironmentObject var viewModelStoreOwner: IOSViewModelStoreOwner + @StateObject var viewModelStoreOwner = IOSViewModelStoreOwner() /// Injects the `AppContainer` from the environment, providing access to application-wide dependencies. @EnvironmentObject var appContainer: ObservableValueWrapper diff --git a/Fruitties/iosApp/iosApp/ui/ContentView.swift b/Fruitties/iosApp/iosApp/ui/ContentView.swift index eddbb9c..c92a4d8 100644 --- a/Fruitties/iosApp/iosApp/ui/ContentView.swift +++ b/Fruitties/iosApp/iosApp/ui/ContentView.swift @@ -39,9 +39,7 @@ struct ContentView: View { value in HStack { NavigationLink { - ViewModelStoreOwnerProvider { - FruittieScreen(fruittie: value) - } + FruittieScreen(fruittie: value) } label: { FruittieView(fruittie: value) } @@ -62,9 +60,7 @@ struct ContentView: View { .toolbar { ToolbarItem(placement: .navigationBarTrailing) { NavigationLink { - ViewModelStoreOwnerProvider { - CartView() - } + CartView() } label: { Observing(mainViewModel.homeUiState) { homeUIState in let total = homeUIState.cartItemCount diff --git a/Fruitties/iosApp/iosApp/ui/FruittieScreen.swift b/Fruitties/iosApp/iosApp/ui/FruittieScreen.swift index c8c4d1f..61e55f9 100644 --- a/Fruitties/iosApp/iosApp/ui/FruittieScreen.swift +++ b/Fruitties/iosApp/iosApp/ui/FruittieScreen.swift @@ -19,7 +19,7 @@ import SwiftUI import shared struct FruittieScreen: View { - @EnvironmentObject var viewModelStoreOwner: IOSViewModelStoreOwner + @StateObject var viewModelStoreOwner = IOSViewModelStoreOwner() @EnvironmentObject var appContainer: ObservableValueWrapper let fruittie: Fruittie diff --git a/Fruitties/shared/build.gradle.kts b/Fruitties/shared/build.gradle.kts index 0a190e7..fd025e2 100644 --- a/Fruitties/shared/build.gradle.kts +++ b/Fruitties/shared/build.gradle.kts @@ -50,26 +50,17 @@ kotlin { // A step-by-step guide on how to include this library in an XCode // project can be found here: // https://developer.android.com/kotlin/multiplatform/migrate - val xcfName = "shared" - iosX64 { - binaries.framework { - baseName = xcfName + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64(), + ).forEach { + it.binaries.framework { + export(libs.androidx.lifecycle.viewmodel) + baseName = "shared" } } - - iosArm64 { - binaries.framework { - baseName = xcfName - } - } - - iosSimulatorArm64 { - binaries.framework { - baseName = xcfName - } - } - // Source set declarations. // Declaring a target automatically creates a source set with the same name. By default, the // Kotlin Gradle Plugin creates additional source sets that depend on each other, since it is @@ -90,7 +81,7 @@ kotlin { implementation(libs.ktor.client.content.negotiation) implementation(libs.ktor.serialization.kotlinx.json) implementation(libs.skie.annotations) - implementation(libs.androidx.lifecycle.viewmodel) + api(libs.androidx.lifecycle.viewmodel) implementation(libs.androidx.paging.common) implementation(libs.androidx.room.runtime) implementation(libs.sqlite.bundled) diff --git a/Fruitties/shared/src/iosMain/kotlin/com/example/fruitties/di/viewmodel/ViewModelStoreUtil.kt b/Fruitties/shared/src/iosMain/kotlin/com/example/fruitties/di/viewmodel/ViewModelStoreUtil.kt index 89384e8..0acafb9 100644 --- a/Fruitties/shared/src/iosMain/kotlin/com/example/fruitties/di/viewmodel/ViewModelStoreUtil.kt +++ b/Fruitties/shared/src/iosMain/kotlin/com/example/fruitties/di/viewmodel/ViewModelStoreUtil.kt @@ -2,7 +2,6 @@ package com.example.fruitties.di.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.ViewModelStore import androidx.lifecycle.ViewModelStoreOwner import androidx.lifecycle.viewmodel.CreationExtras import kotlinx.cinterop.BetaInteropApi @@ -18,7 +17,7 @@ import kotlin.reflect.KClass @Suppress("unused") // Android Studio is not aware of iOS usage. @OptIn(BetaInteropApi::class) @Throws(IllegalStateException::class) -fun ViewModelStore.getViewModel( +fun ViewModelStoreOwner.viewModel( modelClass: ObjCClass, factory: ViewModelProvider.Factory, key: String?, @@ -30,9 +29,3 @@ fun ViewModelStore.getViewModel( val provider = ViewModelProvider.create(this, factory, extras ?: CreationExtras.Empty) return key?.let { provider[key, vmClass] } ?: provider[vmClass] } - -/** - * The ViewModelStoreOwner isn't used anywhere in the project, therefore it's not visible for Swift by default. - */ -@Suppress("unused") -interface SwiftViewModelStoreOwner : ViewModelStoreOwner