Adding objects To-Many Relationships RLMObject

I'm starting use Realm.io and I need to add or update a To-Many relationship RLMObject. Imagine I have RLMObjects like this:

#import <Realm/Realm.h>

@class Person;

// Dog model
@interface Dog : RLMObject
@property NSInteger id;
@property NSString *name;
@end
RLM_ARRAY_TYPE(Dog) // define RLMArray<Dog>

// Person model
@interface Person : RLMObject
@property NSString             *name;
@property NSDate               *birthdate;
@property RLMArray<Dog *><Dog> *dogs;
@end
RLM_ARRAY_TYPE(Person) // define RLMArray<Person>

Dogs RLMObject has a primary Key (id) and I'm reading a json with one person and various Dogs. How can I add the Person and their Dogs?

I'll loop json person and dogs array. If I use above code for example, realm warning about primary key violation on Dogs object:

RLMRealm *realm = [RLMRealm defaultRealm];
Dogs *dog = [[Dogs alloc] init];
[realm beginWriteTransaction];
   dog.id = 1;
   dog.name = @"Lupi";
   [realm addOrUpdateObject:dog];
   dog.id = 2;
   dog.name = @"rex";
   [realm addOrUpdateObject:dog]; 
[realm commitWriteTransaction];

Person *newPerson = [[Person alloc] init];
    [realm beginWriteTransaction];
        newPerson.id = 1;
        newPerson.name = @"John";
        [newPerson.dogs addObject:dog];
        [realm addOrUpdateObject:newPerson];
    [realm commitWriteTransaction];

Upvotes: 0

Views: 355

Answers (1)

kishikawa katsumi
kishikawa katsumi

Reputation: 10573

If you get this error 'Primary key can't be changed after an object is inserted.', the reason is because you're trying to use the same object.

dog.id = 1;
dog.name = @"Lupi";
[realm addOrUpdateObject:dog];

dog.id = 2; // This is not allowed. The primary key of the object that was saved once can not be changed.
dog.name = @"rex";
[realm addOrUpdateObject:dog];

Realm object is not a just value object. When the Realm object is saved once, it will be changed to a special object that connected to the database.

So dog.id = 2; means that you will change the object that you just saved.

You should create new instance every time when you'd like to save new objects. Like the following:

Dog *dog1 = [[Dog alloc] init];
dog1.id = 1;
dog1.name = @"Lupi";
[realm addOrUpdateObject:dog1];

Dog *dog2 = [[Dog alloc] init];
dog2.id = 2;
dog2.name = @"rex";
[realm addOrUpdateObject:dog2];

[realm commitWriteTransaction];

Create objects from JSON

If you will create new objects from JSON like the following:

{
  "person": {
    "id": 1,
    "name": "foo",
    "birthdate": "1980/10/28",
    "dogs": [
      {
        "id": 1,
        "name": "bar"
      },
      {
        "id": 2,
        "name": "baz"
      }
    ]
  }
}

You can just loop the dogs array, create new Realm objects every loop.

NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

NSDictionary *person = json[@"person"];

[realm beginWriteTransaction];

Person *newPerson = [[Person alloc] init];
newPerson.id = [person[@"id"] integerValue];
newPerson.name = person[@"name"];

NSArray *dogs = person[@"dogs"];
for (NSDictionary *dog in dogs) {
    Dog *newDog = [[Dog alloc] init];
    newDog.id = [dog[@"id"] integerValue];
    newDog.name = dog[@"name"];
    [realm addOrUpdateObject:newDog];
}

[realm addOrUpdateObject:newPerson];

[realm commitWriteTransaction];

Upvotes: 1

Related Questions