I am mapping a large data set to Core data using Restkit. I am making a call to get data from a web service, storing it in core data and then displaying it from core data. Here is my code.
+(void) setupManagedObjectStore
{
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"momd"];
NSManagedObjectModel *managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
RKManagedObjectStore *store = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
NSError *error = nil;
BOOL success = RKEnsureDirectoryExistsAtPath(RKApplicationDataDirectory(), &error);
if (! success)
{
NSLog(@"Failed to create Application Data Directory at path '%@': %@", RKApplicationDataDirectory(), error);
}
NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"MyFile.sqlite"];
//Does lightweight migration automatically
NSDictionary *options = @{
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES
};
NSPersistentStore *persistentStore = [store addSQLitePersistentStoreAtPath:path fromSeedDatabaseAtPath:nil withConfiguration:nil options:options error:&error];
if (! persistentStore)
{
NSLog(@"Failed adding persistent store at path '%@': %@", path, error);
}
[store createManagedObjectContexts];
store.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:store.persistentStoreManagedObjectContext];
[[RKObjectManager sharedManager] setManagedObjectStore:store];
}
Get data, deletes existing data in the table and adds new data
-(void)getData:(SuccessBlock)successBlock withFailure:(FailureBlock)failureBlock objectId:(NSString *) objectId
{
[self deleteData:objectId]; //Deletes the data from the entity
NSString *path = [NSString stringWithFormat:@"getData/%@",objectId];
[[RKObjectManager sharedManager] getObjectsAtPath:path parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult){
NSLog(@"SUCCESS in getting data");
if(successBlock){
successBlock([self getDataFromCoreData:objectId]);
}
failure:^(RKObjectRequestOperation *operation, NSError *error){
NSLog(@"FAILURE in getting data");
}
];
}
-(NSArray *)getDataFromCoreData : objectId
{
NSArray *array = [[NSArray alloc] init];
NSManagedObjectContext *context = [[[RKObjectManager sharedManager] managedObjectStore] mainQueueManagedObjectContext];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"MyEntity"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"objectId= %@", objectId];
NSError *error;
array = [context executeFetchRequest:fetchRequest error:&error];
return array;
}
My core data model has lots of 1:many relationships, and my Restkit mapping was quite slow, hence to improve the performance I added the line
store.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:store.persistentStoreManagedObjectContext];
That did improve the performance, but after the deleteData() call, Restkit mapping seems to happen alternately.
Call getData - 1: getDataFromCoreData returns data
Call getData - 2: getDataFromCoreData returns empty array, the table is empty
Call getData - 3: getDataFromCoreData returns data
Call getData - 4: getDataFromCoreData returns empty array, the table is empty
If I comment out the store.managedObjectCache line, everything works fine, and getDataFromCoreData always returns data. But Restkit mapping becomes super slow.
I can't find enough documentation on RKInMemoryManagedObjectCache to understand what exactly is going on..
Can someone help me understand why it would work this way? Or maybe suggest a better way to improve Restkit mapping performance?
EDIT: Adding delete code
-(void)deleteData : objectId
{
NSManagedObjectContext *context = [[[RKObjectManager sharedManager] managedObjectStore] mainQueueManagedObjectContext];
NSArray *array = [self getDataFromCoreData: objectId];
for (NSManagedObject *product in array)
{
[context deleteObject:product];
}
}