Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

magicalrecord deleting non-imported data

Imagine the following relation in CoreData

Recipe < --- >> Ingredient

I'm using MagicalRecord to regularly import the server database (JSON API) with my local CoreData database.

So, if I import Recipe 1 with Ingredient 1 like this:

{
  id:1,
  name: "Recipe 1",
  ingredients: [{
    name: 'Ingredient 1'
  }]
}

So for so good, MagicalRecord creates the two entities and links them together.

The problem appears when the server changes to the following:

{
  id:1,
  name: "Recipe 1",
  ingredients: [{
    name: 'Ingredient 2' <-- Notice here
  }]
}

What MagicalRecord does is create the Ingredient 2record (correct), link it to be the only ingredient for Recipe 1(correct). But if I search for Ingredients, I found 2 records on my CoreData database.

So the questions is, is it possible to keep track of "deleted" objects when importing, and deleting them?

like image 769
rubenfonseca Avatar asked Nov 26 '25 14:11

rubenfonseca


2 Answers

The real problem here is that MagicalRecord seems to be importing duplicates. This problem should have been resolved in a recent update, however, if you're still having issues, I suggest opening a ticket on the project issues page

like image 182
casademora Avatar answered Nov 29 '25 16:11

casademora


I have worked around this problem by following this process.

  1. Run a query on your core data store that will return the values you expect for any given server request. Find all the objectIDs for every object found by the query that is expected to be returned by the server.
  2. Make the server request and import the data.
  3. Before saving get all updated objects from the context you just used to import the data.
  4. Delete any object in your original list of objectIDs that is not in your list of updated objectIDs

This approach should achieve the desired behaviour for any given request. Just be aware you will still possibly be deleting records referenced from elsewhere, so only use this approach if they can be recreated by other future requests.

Import Code

NSArray *existingObjectIDs = [self existingObjectIDsForYourQuery];

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
                    [Recipe MR_importFromObject:response inContext:localContext];
                    NSArray *objectIDs = [[[localContext updatedObjects] allObjects] valueForKey:@"objectID"];
                    [self deleteLocalObjectsWithObjectIDs:existingObjectIDs excludingImportedObjectIDs:objectIDs];
}];

Delete Code

- (void)deleteLocalObjectsWithObjectIDs:(NSArray *)existingObjectIDs excludingImportedObjectIDs:(NSArray *)importedObjectIDs {
    NSMutableArray *objectsToDelete = [NSMutableArray arrayWithArray:existingObjectIDs];

    for ( NSManagedObjectID *objectID in importedObjectIDs ) {
        [objectsToDelete removeObject:objectID];
    }

    [MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {
        for ( NSManagedObjectID *objectID in objectsToDelete ) {
            NSManagedObject *object = [localContext existingObjectWithID:objectID error:nil];

            if ( object ) {
                [localContext deleteObject:object];
            }
        }
    }];
}
like image 39
nacross Avatar answered Nov 29 '25 14:11

nacross



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!