user4992124 user4992124 - 4 months ago 59x
Objective-C Question

Add or Update object on RLMArray?

I have an app with Realm and CloudKit built in. The app fetches the data from the CloudKit container and then adds it to Realm. One of the two fetches has some linked Realm models though, and that's where the difficulties come in.

My current code looks like this:

NSPredicate *predicate = [NSPredicate predicateWithValue:YES];

CKDatabase *publicDatabase = [[CKContainer containerWithIdentifier:@""] publicCloudDatabase];
CKQuery *query = [[CKQuery alloc] initWithRecordType:@"Restaurant" predicate:predicate];
CKQueryOperation *queryOp = [[CKQueryOperation alloc] initWithQuery:query];
queryOp.recordFetchedBlock = ^(CKRecord *record)
RLMRealm *realm = [RLMRealm defaultRealm];

Restaurant *restaurant = [[Restaurant alloc] init]; = record[@"Name"];
restaurant.explanation = record[@"Explanation"];

Table *firstTable = [[Table alloc] init];
firstTable.number = record[@"FirstNumber"];

[restaurant.tables addObject:firstTable];

Table *secondTable = [[Table alloc] init];
secondTable.number = record[@"SecondNumber"];

[restaurant.tables addObject:secondTable];

set.localID = [record[@"localID"] integerValue];

RLMResults<Area *> *areas = [Area objectsWhere:@"postalCode = 90210"];
Area *area = [areas objectAtIndex:0];

[realm beginWriteTransaction];

[area.restaurants addObject:restaurant];

[realm commitWriteTransaction];

queryOp.queryCompletionBlock = ^(CKQueryCursor *cursor, NSError *error)
NSLog(@"Fetching succeeded");

queryOp.resultsLimit = CKQueryOperationMaximumResults;
[publicDatabase addOperation:queryOp];

Now, this is a simplification of my code, but it recreates the error I get. Realm throws:
Can't set primary key property 'localID' to existing value '26306'.
. I believe this is caused by the fact that the exact
is already in the
. I should probably check if the Restaurant is in the array and if not, add it. But how can I do this? How can I prevent this from happening?


You can check if an object with the specified primary key already exists by calling + [RLMObject objectForPrimaryKey:] and checking that it doesn't return nil. Primary key properties are automatically indexed by Realm, so this lookup is performed extremely quickly. :)

Additionally, just to clarify how Realm works, this isn't checking to see if that specific object is in your RLMArray or not; it's whether the object is in the Realm database itself. As such, in your case, it may be necessary to first query Realm for that object via its primary key, and if it turns out to not be nil to then check to see if that object is already in the array.