Best practices for having @RealmObservedObject inside a ViewModel (ObservableObject)

I want to do something like this to keep all my data logic in a ViewModel

class ViewModel: ObservableObject {
      @RealmObservedObject var dog: Dog 
   
      func updateDogType( ) { ... } 
}

struct dogView: View {
   @StateObject viewModel: ViewModel
   
   init(dog: Dog) {
        _viewModel = StateObject(wrappedValue: ViewModel(dog: dog)) 
   }

    var body: some View {
           Text(viewModel.dog.type)
    }
}

I noticed that the view doesn’t always get updated right away when the model changes. I guess the name @RealmObservableObject implied it doesn’t work properly if it is nested inside a ViewModel?

Do we always need to have both @RealmObservableObject and a ViewModel? Doesn’t feel right to have two sources of truth.

Hi @Siwei_Kang,
Nested @ObservableObjects will not work without some tuning.
The Dog object will notify ViewModel but ViewModel must propagate the update notification to the DogView and you have to do that manually.

For example you can do something like this:

// Thanks heckj for solution
// https://stackoverflow.com/a/66664642/113127
class DogView: ObservableObject {
    @ObservedRealmObject var dog: Dog
    var anyCancellable: AnyCancellable? = nil
    init(_ dog: Dog) {
        self.dog = dog
        anyCancellable = dog.objectWillChange.sink { [weak self] (_) in
            self?.objectWillChange.send()
        }
    }
}
2 Likes

Thanks Pavel! it makes sense to manually trigger objectWillChange. However, I got an exception **Terminating app due to uncaught exception 'RLMException', reason: 'Frozen Realms do not change and do not have change notifications.'** Any idea how I get around that?

1 Like

Actually I got around it with Dog.thaw().objectWillChange.sink { ... }

2 Likes

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.