Question

my use case is very simple. I need to

  • create a request NSManagedObject, ✓ works
  • pass it to e.g. postObject: method from Restkit, ✓ works
  • receive a response NSManagedObject in the completion block, ✓ works
  • process it and, ✓ works
  • delete both the request and the response objects using MR_deleteEntity, ✘ does not work

I'd like to use just MagicalRecord to create/delete/manage the entities.

The issue:

When I call the asynchronous save method from the MagicalRecord toolkit and after I exit the app I can still see the entities in the sqlite db file. After restart of the app new objects are added in the db without deleting a single instance although I explicitly call MR_deleteEntity on the objects. I admit the context management is something I yet have not grasped fully.

I am using the following setup to connect MagicalRecord with Restkit:

// 1. Setup the core data stack with the automigration 

[MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:[GVUserDefaults standardUserDefaults].applicationStoreName];

// 2. Initialize managed object store

RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithPersistentStoreCoordinator:[NSPersistentStoreCoordinator MR_defaultStoreCoordinator]];

// 3. create the persistentStoreManagedObjectContext and the mainQueueManagedObjectContext:

[managedObjectStore createManagedObjectContexts];

// 4. set the default and the root saving context:

[NSManagedObjectContext MR_defaultStoreCoordinator:managedObjectStore.mainQueueManagedObjectContext];
[NSManagedObjectContext MR_setRootSavingContext:managedObjectStore.persistentStoreManagedObjectContext];


// 5. create RestKit manager:

self.rkManager = [TSNRKObjectManager managerWithBaseURL:[NSURL URLWithString:[self serverURL]]];
self.rkManager.requestSerializationMIMEType = RKMIMETypeJSON;
self.rkManager.managedObjectStore = managedObjectStore;

Question

I am trying to delete the request and the response objects this way:

[self saveWithBlock:^(NSManagedObjectContext *localContext) { // calls [MagicalRecord saveWithBlock:block completion:completion]

   // some additional processing, getting data from the response         

   [loginResponse MR_deleteEntity];
   [loginRequest MR_deleteEntity];

} completion:^(BOOL success, NSError *error) {

   // some additional processing
}];

But I always get this message in the log:

-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x110906470) NO CHANGES IN ** UNNAMED ** CONTEXT - NOT SAVING

I am using this page as reference https://gist.github.com/tonyarnold/4694673. The contexts for the creation of the request and the response entity are the same? What context is Restkit using for creation of the entities? Should I create the request entity also within the block in [MagicalRecord saveWithBlock:block completion:completion]? The example from https://github.com/blakewatters/RKMagicalRecord does not include the automigration setup and the asynchronous saving methods.

UPDATE:

Is this an acceptable solution? (I mean clean, graceful deletion):

        [self.loginRequest MR_deleteEntity];
        [self.loginRequest.managedObjectContext MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {
            // log
        }];



        [self.loginResponse MR_deleteEntity];
        [self.loginResponse.managedObjectContext MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {
            // log
        }];

I have tested this and it works.

UPDATE 2

In the completion block triggered from Restkit's postObject:... call, I can cleanup the entities from the persistent store this way:

    [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {

        [[self.loginRequest MR_inContext:localContext] MR_deleteEntity];
        [[self.loginResponse MR_inContext:localContext] MR_deleteEntity];

    } completion:^(BOOL success, NSError *error) {

        if(success) {

            self.loginRequest = nil;
            self.loginResponse = nil;

            // log, update ui

        } else {

            // log error
        }

    }];
Was it helpful?

Solution

You misunderstand the saving semantics for your multiple contexts. When you call saveWithBlock: you need to transfer all of your managed objects to that new local context that is created for you before you operate on them, otherwise the context has no changes and isn't saved. To transfer you need to get the managed object ids and find the existingObjectWithID:error:.

In this case, for 2 object deletion a you are better off deleting the objects directly from the main context (which is the one they belong to) and saving it up to the persistent store.

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