1
votes

Short version of my problem: I'm deleting an object and after I do a fetch that returns the previously deleted object.

I'm following this architecture: SyncService -> Persistence Service -> NSManagedObject

All my classes in Persistence Service layer are children of the following class:

# 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

Before the deletion, I fetch the object in my main context:

# 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];
        }
    }
}

.

# PseudoLeadPersistenceService.m
-(NSArray *) getAllParentPseudoLeads {
    return [PseudoLeadDAO findAllParentPseudoLeadsInContext:self.context.parentContext];
}

And here I fetch and actually delete the object in my subcontext:

# 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];
}

Then the -(void) synchronize is called again and the deleted object shows up again as a fault. At this point, I can fetch as many times as I want and it will be returned. It only goes away when it comes to -(void) deletePseudoLeadById:(NSNumber *)pseudoLeadId andEventId:(NSNumber *)eventId method again and the fault is fired.

I'll appreciate any help given. Thanks!

1

1 Answers

0
votes

The problem was concurrency. The thread started to save the context wasn't getting done before the next fetch.

I solved the problem by using performBlockAndWait:

# 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];

            }];
        }];
    }];
}

.

# 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];
}