0
votes

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];
    }
}
1
Show the delete method and your mapping code - Wain

1 Answers

0
votes

I figured it out. I had to do a saveToPersistentStore after the deleteData method call.

I am using persistentStoreManagedObjectContext for the managedObjectCache and mainQueueManagedObjectContext for saving to core data and retrieval. persistentStoreManagedObjectContext vs mainQueueManagedObjectContext

So saving the context by using saveToPersistentStore, after deleting and before making the web service call fixed the problem.