I have spent hours upon hours trying to figure out how to setup the models for object relationships and create/delete many-to-many relationships in Realm using Objective-C. The documentation has been less than helpful. I could use some guidance on whether to use RLMArray or RLMLinkingObjects... If I use RLMLinkingObjects to set up my to-many relationships, I cannot use addObject:
to create the relationships, and I cannot find any way to delete a relationship. I am moving from a Core Data relational database and have several many-to-many relationships that I am trying to model, and this just makes no sense at all to me. The only documentation showing a many-to-many relationship shows a class relating two of its own properties. One of the properties uses RLMArray and the other uses RLMLinkingObjects. This makes no sense to me, since a many-to-many relationship is supposed to be bi-directional, and relationships should be able to be added or deleted via either side. Maybe I am thinking about this wrongly, but I am lost and would appreciate some help.
Many
relationships in Realm are modelled with RLMArray
. Every to-one and to-many relationship however creates its own corresponding inverse relationship, which is modelled by RLMLinkingObjects
(the objects that are linking to this current object).
So RLMArray
is a unidirectional link to multiple objects, and RLMLinkingObjects
is a unidirectional inverse link to the objects that are linking to the object. The relationship can be modified via the RLMArray
, which will automatically manage its inverse relation (corresponding RLMLinkingObjects
).
If you need to modify the relationship from the target, then you can find the object with the RLMArray
using a link query across the linking objects via primary key.
import <Realm/Realm.h>
@class Person;
// Dog model
@interface Dog : RLMObject
@property NSInteger id;
@property NSString *name;
@property (readonly) RLMLinkingObjects *owners;
@end
RLM_ARRAY_TYPE(Dog) // define RLMArray<Dog>
// Person model
@interface Person : RLMObject
@property NSInteger id;
@property NSString *name;
@property NSDate *birthdate;
@property RLMArray<Dog *><Dog> *dogs;
@end
RLM_ARRAY_TYPE(Person) // define RLMArray<Person>
// Implementations
@implementation Dog
+ (NSDictionary *)linkingObjectsProperties {
return @{
@"owners": [RLMPropertyDescriptor descriptorWithClass:Person.class propertyName:@"dogs"],
};
}
+ (NSString *)primaryKey {
return @"id";
}
+ (NSArray *)indexedProperties {
return @[@"name"];
}
@end
@implementation Person
+ (NSString *)primaryKey {
return @"id";
}
+ (NSArray *)indexedProperties {
return @[@"name"];
}
@end
So when you modify person.dogs
in a transaction, then dog.owners
will be automatically updated.
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
Person *jim = [[Person objectsWhere:@"name == 'Jim'"] firstObject];
// Jim is owner of Rex
Dog * rex = [[Dog objectsWhere:@"name == 'Rex'"] firstObject];
[jim.dogs addObject:rex]; // <-- now rex's `owners` contains `jim`
}];
You can read more about relationships in Realm here.