Question

I perform some work using an NSBlockOperation and inside this block the persistent store loses its persistent stores.

the following code:

- (void) eraseCoreData_ManagedObjectsInArray:(NSArray *) arrayOfManagedObjectsToDelete usingManagedContext:(NSManagedObjectContext *) managedObjectContext
{
    NSLog(@"Managed object context is %@", managedObjectContext);
    NSLog(@"----->Persistent store of the deletion context has %d stores", [managedObjectContext.persistentStoreCoordinator.persistentStores count]);

    // add the operation to the queue with a block
    [self.coreDataDeletionQueue addOperationWithBlock:^{

    for (NSManagedObject *objectToDelete in arrayOfManagedObjectsToDelete) {
        [managedObjectContext deleteObject:objectToDelete];
    }

    NSLog(@"Managed object context in operation block is %@", managedObjectContext);
    NSLog(@"Persistence store coordinator in operation block is %@", managedObjectContext.persistentStoreCoordinator);
    NSLog(@"Persistent store of the deletion context in operation block has %d stores", [managedObjectContext.persistentStoreCoordinator.persistentStores count]);

    NSError *saveError = nil;
    if (![managedObjectContext save:&saveError]) {
        NSLog(@"Couldn't save Core-Data state for the deleted objects result: %@", [saveError localizedDescription]);
    }
    }];
}

logs this out:

Managed object context is < NSManagedObjectContext: 0xa46ff10 >

----->Persistent store of the deletion context has 1 stores

Managed object context in operation block is < NSManagedObjectContext: 0xa46ff10 >

Persistence store coordinator in operation block is < NSPersistentStoreCoordinator: 0xa1a45e0 >

Persistent store of the deletion context in operation block has 0 stores

* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'This NSPersistentStoreCoordinator has no persistent stores. It cannot perform a save operation.'

I am not sure why this sudden lose of stores, could it be due to the fact that this is running in a test suite that I set to use an in memory store and the memory is not shared with this NSOperationQueue that executes the blocks?

Was it helpful?

Solution

My guess you are using your code in the wrong manner.

First, each thread must have its own context. So, inside the block operation you need to create a new context and use it within that block.

NSManagedObjectContext *blockContext = [[NSManagedObjectContext alloc] init];
[blockContext setPersistentStoreCoordinator:[managedObjectContext persistentStoreCoordinator]];

Then, if you need to share objects within contexts, use NSManagedObjectID and not NSManagedObject. Before creating that block save the main context or you will have only temporary ids. Otherwise use - (BOOL)obtainPermanentIDsForObjects:(NSArray *)objects error:(NSError **)error to obtain permanent ids without saving.

NSArray *objectIDs = [arrayOfManagedObjectsToDelete valueForKey:@"objectID"];

Within the block use - (NSManagedObject *)existingObjectWithID:(NSManagedObjectID *)objectID error:(NSError **)error to retrieve the object you are interested in through blockContext.

Your code could look like

NSArray *objectIDs = [arrayOfManagedObjectsToDelete valueForKey:@"objectID"];

// add the operation to the queue with a block
[self.coreDataDeletionQueue addOperationWithBlock:^{

    NSManagedObjectContext *blockContext = [[NSManagedObjectContext alloc] init];
    [blockContext setPersistentStoreCoordinator:[managedObjectContext persistentStoreCoordinator]];

    NSError* error = nil;
    for (NSManagedObject *objectID in objectIDs) {
        // some error handling here...
        NSManagedObject* objectToDelete = [existingObjectWithID:objectID error:&error];
        [blockContext deleteObject:objectToDelete];
    }

    if (![blockContext save:&error]) {
        NSLog(@"Couldn't save Core-Data state for the deleted objects result: %@", [error localizedDescription]);
    }
}];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top