Set shouldDeleteInaccessibleFaults:
to YES
and inaccessible/unfulfillable faults will be deleted. This solves the immediate problem.
The WWDC 2015 session What's New in Core Data talks about this a little bit. Both NSBatchDeleteRequest
and NSBatchUpdateRequest
modify the persistent store without the participation of the NSManagedObjectContext
- which will result in the context's view of the data being inconsistent with the store.
The in-memory copy of the deleted object needs to be updated in the NSManagedObjectContext
- have the batch delete request return the object IDs of the deleted objects and tell the NSManagedObjectContext
to refresh those IDs.
This would look something like this:
[managedObjectContext performBlock:^{
NSBatchDeleteRequest batchDeleteRequest = [NSBatchDeleteRequest alloc] initWithFetchRequest:fetchRequest];
NSBatchDeleteResult result = nil;
result = [managedObjectContext executeRequest:batchDeleteRequest error:&error];
if ([[result result] count] > 0){
[managedObjectContext performBlock:^{
NSArray<NSManagedObjectID *> *objectIDs = (NSArray<NSManagedObjectID *>)[result result];
[objectIDs enumerateObjectsUsingBlock:^(NSManagedObjectID *objID, NSUInteger idx, BOOL *stop) {
NSError *error = nil;
NSManagedObject *obj = [managedObjectContext existingObjectWithID:objID error:&error];
if (![obj isFault] ) {
[managedObjectContext refreshObject:obj mergeChanges:YES];
}
}];
}];
}
}];
When the batch delete runs, relationships will be deleted or nullified, but a cascading set of delete rules may not be executed, and validation rules will not be executed - it is up to your application to ensure data integrity when using any of the batch change requests.
Your data model may require you to issue multiple delete requests to prevent related objects from being orphaned but still findable. For example, you may need a second batch delete to locate previously related entities that now have empty relationships. The predicate for such a request may look like:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"toMany.@count == 0"];
Or may use a subquery, etc.