1

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.

SAHM
  • 4,078
  • 7
  • 41
  • 77
  • 1
    `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. – EpicPandaForce Jun 13 '17 at 23:58
  • At this point, could you possibly direct me to some code that demonstrates this? I am not trying to get someone to do my work for me - I truly have spent hours and researched it as thoroughly as I possibly can and do not understand how to set this all up. – SAHM Jun 14 '17 at 00:01
  • 1
    ...well, I'll try to put some snippets together from the docs. I'm not well-versed in anything iOS (especially if you see my post history and tags) – EpicPandaForce Jun 14 '17 at 00:02
  • I do appreciate it - but I've scoured the docs and this still doesn't make any sense to me. I guess I am just not grasping it. – SAHM Jun 14 '17 at 00:03
  • For a to-many, do we just randomly assign one end of the relationship as RLMArray and the other as RLMLinkingObjects? – SAHM Jun 14 '17 at 00:04
  • And even for a one-to-many, do we assign the list as RLMArray or RLMLinkingObjects? It seems there is a choice to be made, and it's just not clear how to go about making it. – SAHM Jun 14 '17 at 00:06
  • 1
    Well pretty much, depending on which side points towards which side. The inverse is auto-managed. For example, you could model `dogs.owner` as the RLMArray, but you could also model `person.dogs` as such. And generally, `person.dogs` makes more sense. `RLMArray` is where you add what belongs to the object, and the linking ones are automatically managed if you add/remove anything to RLMArray. – EpicPandaForce Jun 14 '17 at 00:07
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/146586/discussion-between-sahm-and-epicpandaforce). – SAHM Jun 14 '17 at 00:08

1 Answers1

2

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.

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • Can a dog have multiple owners in your example? Is this a many-to-many relationship you are modeling? – SAHM Jun 14 '17 at 00:22
  • 1
    A person can have multiple dogs. Afterwards the dog doesn't really care whether it's one or many that's pointing to it, it's always modelled as linking objects which is 0..* – EpicPandaForce Jun 14 '17 at 00:23
  • I am just trying to figure out if this is how I model a many-to-many. So, if a dog can have multiple owners, that would help me understand. – SAHM Jun 14 '17 at 00:24
  • 1
    `RLMLinkingObjects` is a list, so technically yes, in this model, a Dog can have multiple owners. It does **not** restrict it to 1 owner, that is for certain. – EpicPandaForce Jun 14 '17 at 00:24
  • So then this is the preferred way to model a many-to-many? If so, what would you change about it to model a many-to-one? For example, what would the code look like if a dog could only have one owner, but an owner could have multiple dogs? – SAHM Jun 14 '17 at 00:26
  • 1
    Then the **Dog** would need to specify `Person *owner;` (NOT array because you said *one*), and then **Person** would have the `RLMLinkingObjects*` field called `dogs`. – EpicPandaForce Jun 14 '17 at 00:26
  • So the person would have RLMLinkingObjects for dogs and not RLMArray for dogs? Is this always the case? – SAHM Jun 14 '17 at 00:27
  • Oh, I thought it had to have one or the other, RLMArray or RLMLinkingObjects – SAHM Jun 14 '17 at 00:29
  • 1
    `RLMArray*` models MANY links. `SomeObject*` models ONE links. `RLMLinkingObjects*` models INVERSE links. – EpicPandaForce Jun 14 '17 at 00:29
  • I get that (to some, limited extent, as you can see), but if I use Person *owner; on Dog, I can use only RLMArray or RLMLinkingObjects for dogs on Person - am I wrong? I am truly not trying to be obtuse (it just comes naturally). – SAHM Jun 14 '17 at 00:31
  • 1
    Actually, then you can only use `RLMLinkingObjects*` for `dogs` field in `Person`, because it is the *inverse* link for `owner`. Well technically you *can* manage multiple links side-by-side, but it makes *your* life more complicated to have two links instead of one where the other direction is auto-managed. But this is all in the docs I linked at the bottom of the answer. – EpicPandaForce Jun 14 '17 at 00:32
  • But is this the case for every one-to-many inverse relationship? RLMLinkingObjects as opposed to RLMArray? I have read the docs, they just left me with many questions. – SAHM Jun 14 '17 at 00:33
  • 1
    Every inverse relationship is modeled with `RLMLinkingObjects*`, yes. Because they are "the objects that are linking to this current object". – EpicPandaForce Jun 14 '17 at 00:34
  • 1
    Okay, I will use Class name/RLMLinkingObjects for one-to-many inverse relationships, and RLMArray/RLMLinkingObjects for many-to-many inverse relationships. – SAHM Jun 14 '17 at 00:35
  • Thank you for all of your help. So much. – SAHM Jun 14 '17 at 00:36