RestKit / CoreData: Duplicate objects inserted instead of merged when requesting the same URL twice

StackOverflow https://stackoverflow.com/questions/22971789

Question

My application uses RestKit to GET from a URL, the payload of which contains a list of objects (hospitals) in JSON. The first time I hit the URL, everything works fine - the payload is correctly transformed into a group of Hospital managed objects and they are inserted into the persistent store (verified by performing a fetch request and comparing the results with the payload).

If I perform the GET a second time from the same URL, returning the same payload, RestKit inserts another group of Hospital objects (identical to the first group) into the persistent store. I would like RestKit to determine that the second group of Hospital objects are identical to the first, and then update the first group of objects if necessary.

The payload contains a unique identifier called provider_number.

I added a provider_number field to the Hospital model and ticked Indexed.

I set the identification attribute on the RKEntityMapping accordingly:

+ (RKEntityMapping *) hospitalMapping {
    RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Hospital" inManagedObjectStore:[RKManagedObjectStore defaultStore]];
    [mapping setIdentificationAttributes:@[ @"provider_number"]];
    [mapping addAttributeMappingsFromDictionary:[self hospitalAttributeDictionary]];
    return mapping;
}

I created the managed object cache on the RKManagedObjectStore, using the persistent MOC, per http://restkit.org/api/latest/Classes/RKManagedObjectRequestOperation.html#overview:

managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];

The RKObjectManager is configured to use the persistent MOC:

RKManagedObjectStore *managedObjectStore = [RKManagedObjectStore defaultStore];
NSManagedObjectContext *managedObjectContext = [managedObjectStore persistentStoreManagedObjectContext];

RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:url];
objectManager.managedObjectStore = managedObjectStore;

The RKObjectManager is further configured with the response descriptor and the requested response MIME type.

The mapping operation is then enqueued:

[objectManager getObjectsAtPath:@""  
                     parameters:nil
                        success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
                           NSError *executeError = nil;
                           if([managedObjectContext saveToPersistentStore:&executeError]) {
                              NSLog(@"Saved hospitals to persistent store.");
                           }
                           else {
                              NSLog(@"Failed to save to data store");
                           }
                        } failure:^(RKObjectRequestOperation *operation, NSError *error) {

                           UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"An Error Has Occurred" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
                           [alertView show];
                        }];

Executing this twice causes duplicate object in the persistent store. What am I missing?

Was it helpful?

Solution

From this log:

restkit.core_data:RKFetchRequestManagedObjectCache.m:124 Found objects '( )' using fetchRequest ' (entity: Hospital; predicate: (provider_number == nil); sortDescriptors: ((null)); type: NSManagedObjectResultType; )'

Restkit is looking for an existing item, but the predicate is wrong: predicate: (provider_number == nil)

It immediately isn't clear why. Put a breakpoint in RKFetchRequestManagedObjectCache.m at the start of managedObjectsWithEntity:attributeValues:inManagedObjectContext: and check back up the stack to find out what attributeValues is being created with and why the provider_number isn't being completed correctly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top