Search code examples
ioscore-datansmanagedobjectcontextmagicalrecord

Magical Records: Loading a record to be updated in a local context


I am currently saving a record using Magical Records as follows:

NSManagedObjectID *objID = [existingItem objectID];
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext){
    CustomNSMO *item;
    if(newItem) item = [CustomNSMO MR_createEntityInContext:localContext];
    else item = [localContext objectWithID:objID]; 
    item.sync = 1;
    item.relID = @"Some String";
 }completion:^(BOOL success, NSError *error) {
   //do something
 }];

This works fine. If I query all items where sync has been set I get back the results I expect i.e.

  NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(sync >= 1)"];
  NSArray *objects = [CustomNSMO MR_findAllSortedBy:@"sync" ascending:YES withPredicate:predicate];

gives me an array of my new or updated objects.

I then (after some server business) want to find all results with sync >= 1 and set it to zero. This is when the strange behaviour occurs. I have been trying to get an array of results within a local context via either

  NSManagedObjectContext *localContext    = [NSManagedObjectContext MR_context];
  NSArray *objects = [CustomNSMO MR_findAllSortedBy:@"sync" ascending:YES withPredicate:predicate inContext:localContext];
  for(CustomNSMO *item in objects) {
     item.sync = 0;
  }
  [localContext MR_saveToPersistentStoreAndWait];

or

  [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext){
    NSArray *objects = [CustomNSMO MR_findAllSortedBy:@"sync" ascending:YES withPredicate:predicate inContext:localContext];
    for (SyncObject *currentObj in objects)
    {
        currentObj.sync = @0;
    }
  } completion:nil];

If relID is set when the item is first created then this is all fine. I can edit the item (changing the relID) and the changes is observed in all contexts. However, if the first time the item is created it has a relID of nil then problems occur after using the code above to do the following:

1) Update the item changing a nil relID to some non-nil value

2) Save the item to the database

3) Load the item (by searching on 'sync')

In any context apart from MR_defaultContext relID stays as nil. If I look at the object in MR_defaultContext then I see the correct updated relID. If I look at it in a different context it is nil. This means that the update of sync on a local context overrides the value of relID on the default context (setting it to nil).


Solution

  • Turns out it is a bug with the database store we are using below Core Data.

    https://github.com/project-imas/encrypted-core-data/issues/118