Nosov Pavel
Nosov Pavel

Reputation: 1571

Duplicate objects in RLMArray one-To-Many Relationships

I have a problem without my realm db. I have these objects:

// Person.h
@interface Person : RLMObject
//... property declarations
@property RLMArray<Dog *><Dog> *dogs;
@end

// Dog.h
@interface Dog : RLMObject
@property NSInteger id;
@property NSString *name;
@end

RLM_ARRAY_TYPE(Dog) // Defines an RLMArray<Dog> type 

// Dog.m
@implementation Dog
+ (NSString *)primaryKey {
    return @"id";
}
@end

And when I make this i will get 2 the same objects in Person.dogs

Person *jim = [[Person alloc] init];
Dog *rex = [[Dog alloc] init];
rex.id = 1;
rex.name = @"Rex";

RLMRealm *realm = [RLMRealm defaultRealm];
[realm beginWriteTransaction];
[realm addObject:jim];
[realm commitWriteTransaction];

[realm beginWriteTransaction];
[jim.dogs addObject:rex];
[realm commitWriteTransaction];

[realm beginWriteTransaction];
[jim.dogs addObject:rex];
[realm commitWriteTransaction];

What i should do that after this i will have only one object with unique primary key? I understand that RLMArray just an array, but early i think that realm realize something that one-to-many relationship have only unique objects.

Here are a screenshots from a Realm browser and Xcode debug area

Realm browser Xcode debug area

here are 3 dogs, because a run my code 3 times, but it doesn't matter, and i can make dogs with my Id but it doesn't matter in this case

custom ids

Upvotes: 2

Views: 830

Answers (2)

Wojtek Dmyszewicz
Wojtek Dmyszewicz

Reputation: 4318

I think it's because you didn't persist anything yet.

If you persist RLMObjects with the same primary key, realm will throw an exception (because of the primary key).

// Update or create jim with with the dogs
[realm beginWriteTransaction];
[Person createOrUpdateInRealm:realm withValue:jim];
[realm commitWriteTransaction];

// Or add Jim with the dogs to Realm with transaction
[realm beginWriteTransaction];
[realm addObject:jim];
[realm commitWriteTransaction];

Edit: I agree with Marius, if you first persist the dogs separately and then after that add it to a Person (one-to-many) you wouldn't have a problem anymore, because realm would throw an exception in the first place when persisting the dogs separately.

Upvotes: 0

marius
marius

Reputation: 7806

RLMArray has array semantics. It doesn't behave like a set, which holds only unique objects. That means you can add the same object multiple times. If you want to have only one object of each type in the end, you should add only one object of each.

The output of the debugger you posted indicates that you run your app 3 times, but the dog had a different id each time, so they are threated as different objects.

If you would use [Person createOrUpdateInRealm:realm withValue:jim];, where jim is either an NSDictionary or a standalone object with just one dog and the id of the dog and the person equals to the ids persisted in your Realm, then you would end up with still having just one person and one dog and all their remaining attributes will have updated values.

Upvotes: 3

Related Questions