Search code examples
ioscore-datamagicalrecord

How to purge an entity and after add new records with magical record


When I request new data I want to delete all the records before adding news. Sometimes there is no changes between the old datas recorded and the new datas.

This is what I tried but my new record are never saved (always 0 records saved)

When I request data:

Autorisation* aut = [Autorisation MR_createEntity];
// setter method

When I want to save:

+(void)saveAutorisationList:(NSMutableArray*)autorisationList{
    NSManagedObjectContext* localContext = [NSManagedObjectContext MR_defaultContext];
    for (Autorisation* aut in [self getAutorisationList]) {
      [aut MR_deleteEntityInContext:localContext];  // method that return all Autorisation
    }
    [localContext MR_saveToPersistentStoreWithCompletion:^(BOOL contextDidSave, NSError * error) {
        for (Autorisation* aut in autorisationList) {
            [aut MR_inContext:localContext];
        }
        [localContext MR_saveToPersistentStoreWithCompletion:nil];
    }];
}

+(NSMutableArray*)getAutorisationList {
    NSManagedObjectContext* localContext = [NSManagedObjectContext MR_defaultContext];
    return [[Autorisation MR_findAllInContext:localContext] mutableCopy];
}

Solution

  • What is going on here is that you're deleting all objects, including those which you want to save. Here is step by step what's going on:

    +(void)saveAutorisationList:(NSMutableArray*)autorisationList {
        // as it seems, here autorisationList is a list of new objects you want to save.
    
        NSManagedObjectContext* localContext = [NSManagedObjectContext MR_defaultContext];
    

    Wrong behavior starts here:

        for (Autorisation* aut in [self getAutorisationList]) {
    

    Here getAutorisationList fetched all objects, currently existing in localContext, old + new ones.

          [aut MR_deleteEntityInContext:localContext];  
          // here you deleted each Autorisation object currently existing, including those you want to save
        }
        ...
    }
    

    Instead, you should find diffs between what you received and what existed before, and delete only those objects which were not received with the update.

    E.g. imagine you had set of objects OldSet = {auth1, auth2, auth3}, and with update you received objects NewSet = {auth2, auth3, auth4}. Diffs for deletion would be

    ToBeDeletedSet = OldSet - NewSet = {auth1}
    

    In this way you will keep the records which you had, and save new records as well.

    Then, your save method will look like this:

    +(void)saveAutorisationList:(NSMutableArray*)updatedAutorisationList{
        NSManagedObjectContext* localContext = [NSManagedObjectContext MR_defaultContext];
        NSMutableArray *oldAutorisationList = [self getAutorisationList];
        [oldAutorisationList removeObjectsInArray: updatedAutorisationList];
        for (Autorisation* aut in oldAutorisationList) {
          [aut MR_deleteEntityInContext:localContext];  // method that return all Autorisation
        }
        [localContext MR_saveToPersistentStoreWithCompletion:^(BOOL contextDidSave, NSError * error) {
            for (Autorisation* aut in updatedAutorisationList) {
                [aut MR_inContext:localContext];
            }
            [localContext MR_saveToPersistentStoreWithCompletion:nil];
        }];
    }