Deleted object being returned in a fetch of Core Data

0

I'm having a "small" problem using Core Data.

This is my architecture:

Synchronizer - > SyncService - > PersistenceService - > NSManagedObject

All classes in the PersistenceService layer inherit this structure:

# PersistenceService.h
#import <Foundation/Foundation.h>

@interface PersistenceService : NSObject

@property (nonatomic, retain) NSManagedObjectContext *context;

-(instancetype) init;
-(void) saveContext;
@end

# PersistenceService.m
@implementation PersistenceService

-(instancetype) init {
    self = [super init];

    if (self) {
        self.context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        self.context.parentContext = [DataManager sharedInstance].managedObjectContext;
    }

    return self;
}

-(void) saveContext {
    NSManagedObjectContext *context = self.context.parentContext;

    [self.context performBlock:^{

        NSError *error;
        [self.context save:&error];

        [context performBlock:^{
            NSError *error;
            [context save:&error];

            [context.parentContext performBlock:^{
                NSError *error;
                [context.parentContext save:&error];

            }];
        }];
    }];

}

@end

At the beginning of the run cycle, my Synchronizer does a fetch of the objects I'm going to need, and I step into the SyncService to operate on them. I always use parentContext for anything other than changing (creating, editing, saving, deleting) the objects themselves:

# Synchronizer.m
-(void) synchronize {
    NSArray *pseudoLeads = [[[PseudoLeadPersistenceService alloc] init] getAllParentPseudoLeads];
    if (pseudoLeads) {
        PseudoLeadDAO *pseudoLead = [pseudoLeads objectAtIndex:0];
        if ([pseudoLead.type isEqualToNumber:[NSNumber numberWithInt:Capture]]) {
            CaptureSyncService *service = [[CaptureSyncService alloc] initWithDelegate:self andPseudoLead:pseudoLead];
            [service executeRequest];
        } else {
            HotleadSyncService *service = [[HotleadSyncService alloc] initWithDelegate:self andPseudoLead:pseudoLead];
            [service executeRequest];
        }
    }
}

After the SyncService finishes its operations, I need to delete the object so that it leaves the queue and the next ones are treated. Here is the code I use to retrieve the object I want to delete in context normal and where I actually delete:

# PseudoLeadPersistenceService.m
-(void) deletePseudoLeadById:(NSNumber *)pseudoLeadId andEventId:(NSNumber *)eventId {
    PseudoLeadDAO *pseudoLeadDAO = [PseudoLeadDAO findPseudoLeadById:pseudoLeadId andEventId:eventId inContext:self.context];
    [self.context deleteObject:pseudoLeadDAO];
    [self saveContext];
}

After that the process starts again in the Synchronizer (or should). The problem is that when you go back to the -(void) synchronize method and fetch, the object that has just been deleted is being returned again. No matter how many fetchs I make at that point, it always comes. The process continues and only when the object arrives again at the method of deletion, which is when attempting to access the properties of the nil object is returned and causes the program to break.

    
asked by anonymous 30.10.2014 / 17:37

1 answer

1

The problem was competition. The thread created saving the contexts was not finalizing before the next fetch occurred.

I solved the problem by adding the following method to PersistenceService.

# PersistenceService.m
-(void) saveContextAndWait {
    NSManagedObjectContext *context = self.context.parentContext;

    [self.context performBlockAndWait:^{

        NSError *error;
        [self.context save:&error];

        [context performBlockAndWait:^{
            NSError *error;
            [context save:&error];

            [context.parentContext performBlockAndWait:^{
                NSError *error;
                [context.parentContext save:&error];

            }];
        }];
    }];
}

Now the method that deletes the object calls this new one:

# PseudoLeadPersistenceService.m
-(void) deletePseudoLeadById:(NSNumber *)pseudoLeadId andEventId:(NSNumber *)eventId {
    PseudoLeadDAO *pseudoLeadDAO = [PseudoLeadDAO findPseudoLeadById:pseudoLeadId andEventId:eventId inContext:self.context];
    [self.context deleteObject:pseudoLeadDAO];
    [self saveContextAndWait];
}
    
30.10.2014 / 19:08