Search code examples
iosobjective-cmultithreadingcore-datamagicalrecord

Magical Record detect no changes in default context


I am using Magical Record for my app so I can make use of their core data stack that should automatically propagate my changes in my worker context (core data thread) to the default context (of the main thread). I have been creating and updating my objects in a core data write queue and everything was working fine.

Then I ran into this issue that Magical Record was able to save my changes on my worker context, but when it tries to save to the default context, it detects no changes and therefore doesn't save.

Where did I do wrong? In the rest of my app, I am creating and updating in pretty much the same way and it works. Please help. Thank you!

Below is the related code:

Where no changes were detected after all these changes:

dispatch_async(CoreDataWriteQueue(), ^{
    if (self.person) {
        FTPerson *localPerson = [FTPerson fetchWithID:self.person.id];
        [localPerson setName:self.nameField.text];
        [localPerson trainWithImages:self.addedImages];
    } else {
        FTPerson *newPerson = [[FTPerson alloc] initWithName:self.nameField.text andInitialTrainingImages:self.addedImages];
        FTGroup *localGroup = [FTGroup fetchWithID:self.group.id];
        [newPerson addGroup:localGroup];
    }
    [[NSManagedObjectContext MR_contextForCurrentThread] MR_saveToPersistentStoreAndWait];
});

I have also tried the saveWithBlock method and no luck:

dispatch_async(CoreDataWriteQueue(), ^{
    [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext){
        if (self.person) {
            FTPerson *localPerson = [FTPerson fetchWithID:self.person.id];
            [localPerson setName:self.nameField.text];
            [localPerson trainWithImages:self.addedImages];
        } else {
            FTPerson *newPerson = [[FTPerson alloc] initWithName:self.nameField.text andInitialTrainingImages:self.addedImages];
            FTGroup *localGroup = [FTGroup fetchWithID:self.group.id];
            [newPerson addGroup:localGroup];
        }
    }];
});

And here is where I created the person and group objects:

dispatch_async(CoreDataWriteQueue(), ^{
        FTPerson *newPerson = [[FTPerson alloc] initWithName:@"test" andInitialTrainingImages:@[[UIImage imageNamed:@"test.jpg"]]];
    });

dispatch_async(CoreDataWriteQueue(), ^{
        FTGroup *newGroup = [[FTGroup alloc] init];
        [self setGroup:newGroup];
    });

Also the init methods:

Person

- (id)initWithName:(NSString *)name andInitialTrainingImages:(NSArray *)images {
    NSManagedObjectContext *context = [NSManagedObjectContext     MR_contextForCurrentThread];
    self = [FTPerson MR_createInContext:context];
    self.name = name;
    self.id = [[NSUUID UUID] UUIDString];
    self.objectIDString = [[self.objectID URIRepresentation] absoluteString];
    self.trainingImages = [[NSMutableArray alloc] init];
    [context MR_saveToPersistentStoreAndWait];
    return self; 
}

Group

- (id)init {
    NSManagedObjectContext *context = [NSManagedObjectContext MR_contextForCurrentThread];
    self = [FTGroup MR_createInContext:context];

    self.id = [[NSUUID UUID] UUIDString];

    self.didFinishTraining = NO;
    self.didFinishProcessing = NO;
    self.photosTrained = @(0);
    self.lastProcessedDate = [NSDate date];

    [context MR_saveToPersistentStoreAndWait];
    return self;
}

FIXED

So the problem ended up being unrelated to magical record. I was adding objects to my core data NSSet incorrectly. Instead of making it a NSMutableSet and do addObject:, I should have:

NSMutableSet *mutablePhotos = [self mutableSetValueForKey:@"photos"];
[mutablePhotos addObject:photo];

Solution

  • So the problem ended up being unrelated to magical record. I was adding objects to my core data NSSet incorrectly. Instead of making it a NSMutableSet and do addObject:, I should have:

    NSMutableSet *mutablePhotos = [self mutableSetValueForKey:@"photos"]; [mutablePhotos addObject:photo];