Realm + Mantle: how to avoid multiple inheritance duplication when integrating both frameworks?

587 Views Asked by At

I have a simple scenario where I want to parse a User model from Json with Mantle and persist it to a realm database:

In order to use the Mantle library, the model interface must extend the MTLModel class like this:

@interface User: MTLModel<MTLJSONSerializing>
@property(nonatomic,copy) NSString *name;
@property(nonatomic,copy) NSString *email;
@end

and in order to persist that model in realm, I have to declare a second interface that extends from RLMObject:

@interface RLMUser:RLMObject
@property(nonatomic,copy) NSString *name;
@property(nonatomic,copy) NSString *email;
@end

As you see I had to implement another type of the User class because I have to extend RLMObject.

is there a way to avoid this kind of duplication?

2

There are 2 best solutions below

1
Siyu On BEST ANSWER

Base on the idea of using the protocol, I created a super class (gist here):

@interface ModelBase : RLMObject <MTLJSONSerializing, MTLModel>

Then as @David Snabel-Caunt said, I ended up implementing some functions of the MTLModel class (copy-paste from MTLModel.m).

Finally to use it, you just need to subclass it.

1
TiM On

Hmmm, you COULD try creating a single class that inherits from both classes down a chain as long as RLMObject is the highest superclass (eg User > MTLModel > RLMObject) and seeing if that works. If MTLModel only works on its data through key-path values, Realm might be able to handle working with it like that.

But in all honesty, if you want to ensure that both classes behave properly as intended, it's probably best not to mix them, and simply copy the data across them when needed.

Thankfully, because RLMObject instances exposes all of the properties it persists through an RLMObjectSchema object, you don't need to manually copy each property manually, and can do it with a pretty minimal amount of code:

User *mantleUser = ...;
RLMUser *realmUser = ...;

// Loop through each persisted property in the Realm object and 
// copy the data from the equivalent Mantle property to it
for (RLMProperty *property in realmUser.objectSchema.properties) {
   id mantleValue = [mantleUser valueForKey:property.name];
   [realmUser setValue:mantleValue forKey:property.name];
}