Skip to content
New issue

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

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

Already on GitHub? # to your account

How to use cMutableStateFlow with custom objects? (SwiftUI) #194

Open
Sinostria opened this issue Aug 17, 2022 · 2 comments
Open

How to use cMutableStateFlow with custom objects? (SwiftUI) #194

Sinostria opened this issue Aug 17, 2022 · 2 comments
Labels
question Further information is requested

Comments

@Sinostria
Copy link

I want use a custom data class within a ViewModel but the view is not updated automatically.
Can someone tell me what's wrong?

The attached example show's what I try to do.
When I change a value inside DataContainer (prop1 or prop2) the UI is not updated.
I want prop1 and prop2 to behave like prop3. (prop3 works)
I already tried many different ways to automatic update the ui but nothing works.

Shared Code:

import dev.icerock.moko.mvvm.flow.cMutableStateFlow
import dev.icerock.moko.mvvm.viewmodel.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow

data class DataContainer(
    var prop1 : String,
    var prop2 : String,
)

class ExampleViewModel: ViewModel() {
    val dataStateFlow = MutableStateFlow(
        DataContainer(prop1 = "1", prop2 = "2")
    ).cMutableStateFlow()

    val prop3 = MutableStateFlow("3")
        .cMutableStateFlow()

    fun extendProp1() {
        dataStateFlow.value.prop1 += "_1"
    }

    fun extendProp2() {
        dataStateFlow.value.prop2 += "_2"
    }

    fun extendProp3() {
        prop3.value += "_3"
    }
}

SwiftUI Code:

import SwiftUI
import MultiPlatformLibrary
import mokoMvvmFlowSwiftUI

struct ContentView: View {
    @ObservedObject var viewModel = ExampleViewModel()

    var body: some View {
        Text(viewModel.binding(\.dataStateFlow, equals: { $0 == $1 }, getMapper: { $0 as DataContainer }, setMapper: { $0 as DataContainer }).prop1.wrappedValue)
        Text(viewModel.binding(\.dataStateFlow, equals: { $0 == $1 }, getMapper: { $0 as DataContainer }, setMapper: { $0 as DataContainer }).wrappedValue.prop2)
        Text(viewModel.binding(\.prop3, equals: { $0 == $1 }, getMapper: { $0 as String }, setMapper: { $0 as NSString }).wrappedValue)

        Button {
            viewModel.extendProp1()
        } label: {
            Text("Extend Prop 1")
        }

        Button {
            viewModel.extendProp2()
        } label: {
            Text("Extend Prop 2")
        }

        Button {
            viewModel.extendProp3()
        } label: {
            Text("Extend Prop 3")
        }
    }
}
@darksider110
Copy link

Same problem/question here! Please help :)

@ln-12
Copy link

ln-12 commented Aug 19, 2022

I think you main misunderstanding is the difference between a simple var and a MutableStateFlow. A var cannot be observed. The framework has no chance of automatically getting notifications if the value updates. On the other hand, MutableStateFlow is specifically designed for that purpose and if you look at the underlying StateFlowImpl you can see that there is a lot going on.
I would highly recommend to read through the basic giude:
https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-mutable-state-flow/
https://developer.android.com/kotlin/flow/stateflow-and-sharedflow

Long story short: this framework has nothing to do with your problem. You would have to do something like this to update the actual flow:

fun extendProp1() {
    dataStateFlow.value = dataStateFlow.value.copy(prop1 = dataStateFlow.value.prop1 + "_1")
}

fun extendProp2() {
    dataStateFlow.value = dataStateFlow.value.copy(prop2 = dataStateFlow.value.prop1 + "_2")
}

@Alex009 Alex009 added the question Further information is requested label Feb 10, 2023
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants