Realm models in modular codebase

Hi :slight_smile:

I’m currently considering migrating from core data to realm, at the same time, i’m modularizing the codebase. While planning the dependency layers I got stuck with a question.

I will move my data models to external modules, but I wanted them to be agnostic of their persistence solution (realm/core data), so I don’t have to import Realm across all other modules/packages.

I thought I could mimic Core Data and have a class that interfaces with realm like this

class NSManagedUserProfile: Object {
    var account: SomeModelFromExternalLibrary
    var paymentMethods: [AnotherModelFromExternalLibrary]
}

This class would stay in the main app target and it would be used to get/set things from Realm, but for the rest of the other modules in the layers above I could use a dependency free UserProfile class.

The problem (and please correct me if I misunderstood the documentation) is that the properties on an Realm.Object class have to be on Realm.EmbeddedObject, which forces me to adopt EmbeddedObject in those models (account, paymentMethods) and have to import Realm in all the modules they are contained :frowning:

For a second I thought Realm.EmbeddedObject was a protocol and tried to conform to it on an extension, but its a superclass.

How can I keep my models in their modules while having my Realm classes on my main app target?

Welcome to the forums - and to Realm!

That is not correct. Properties on objects can be any of the directly supported types and then if you want to persist an unsupported type, it can be Type Projected to supported types. An EmbeddedObject behaves more like a var, a String or Int that’s a property of the parent class.

For clarity, an Embedded Object is and object that can be re-used as a property of other objects but the object itself is embedded (becomes part of) the parent objects structure. e.g. it not a separate object in Realm and cannot be queried independently of it’s parent object.

An example with some psuedo-code

class PersonClass: Object {
    embeddedDog: EmbeddedDogClass
}

class EmbeddedDogClass: EmbeddedObject {
    name = ""
}

If a person and an embedded dog are instantiateed, and the dog is added to the person, it becomes part of the person, there is no separate, managed dog - so, the underlying data looks like this

person
   dog
     name = spot

whereas if we set it up so the dog is an Object instead of EmbeddedObject

class PersonClass: Object {
    dog: DogClass
}

class DogClass: Object {
    name = ""
}

and a dog is added to the person, it is a reference to the managed DogObject

person
    reference to the Dog object

There are a number of ways. As mentioned above, if you want to persist data that is not a directly supported type, it can be Type Projected.

However, and I may not fully understand the use case, it appears the desire is to isolate the objects to keep them agnostic of their persistence. While it can be done, going down that path will eliminate a lot of the power and flexibility Realm offers.

In a nutshell, Realm objects can be observed, react to changes and are lazily loaded which makes them very memory friendly even on massive datasets. “Agnostizising” them (is that a word?) may remove those features - which is giving up a lot.

I would suggest modeling your data using Realm objects and working within the Realm eco-system as there are a LOT of benefits and very few, if any, downsides.

@Jay thank you very much for the explanation! :pray:

This is interesting. I’m probably going for a separate module dedicated to Models + Realm to keep these benefits.

Again, thank you!