Skip navigation.
 
mlCore Data merge and "statement is still active" error?
FROM : Michael Link
DATE : Tue Jun 03 22:37:47 2008

The goal is to do insertions/changes/deletes on a background thread 
and then after a save merge those changes into the main threads 
managed object context and thus update the UI.

I have a situation where NSManagedObjectContextDidSaveNotification is 
forwarded from a background thread's managed object context to the 
main thread's managed object context (each thread has it's own managed 
object context). The main thread does some processing like this (in a 
subclass of NSPersistentDocument).

- (void)_mergeChangesFromContextDidSaveNotification:
(NSNotification*)notification
{
   NSManagedObjectContext* __managedObjectContext = [self 
managedObjectContext];
   NSDate* __date = [[[NSFileManager defaultManager] 
fileAttributesAtPath:[[self fileURL] path] traverseLink:YES] 
objectForKey:NSFileModificationDate];
   
   [__managedObjectContext 
mergeChangesFromContextDidSaveNotification:notification];
   [__managedObjectContext processPendingChanges];
   [[__managedObjectContext undoManager] enableUndoRegistration];
   
   NSLog(@"%s *1* hasChanges=%d", __FUNCTION__, [__managedObjectContext 
hasChanges]);
   
   [self setFileModificationDate:__date];
   
   if ([__managedObjectContext hasChanges]) {
       [self saveDocument:self];
   }
}

- (void)mergeChangesFromContextDidSaveNotification:
(NSNotification*)notification
{
   NSManagedObjectContext* __managedObjectContext = [self 
managedObjectContext];
   
   NSLog(@"%s *0* hasChanges=%d", __FUNCTION__, [__managedObjectContext 
hasChanges]);
   
   if ([__managedObjectContext hasChanges]) {
       NSDate* __date = [[[NSFileManager defaultManager] 
fileAttributesAtPath:[[self fileURL] path] traverseLink:YES] 
objectForKey:NSFileModificationDate];
       
       [self setFileModificationDate:__date];
       [self saveDocument:self];
   }
   
   [[__managedObjectContext undoManager] disableUndoRegistration];
   
   for (NSManagedObject* __object in [[notification userInfo] 
objectForKey:NSUpdatedObjectsKey]) {
       [__managedObjectContext refreshObject:[__managedObjectContext 
objectWithID:[__object objectID]] mergeChanges:NO];
   }
   
   [self 
performSelector
:@selector(_mergeChangesFromContextDidSaveNotification:) 
withObject:notification afterDelay:0.0];
}

If I forgo the refreshObject:mergeChanges: the error doesn't occur, 
but then another problem occurs where sometimes a relationship doesn't 
merge correctly between 2 objects (even when there are no changes in 
the main thread's managed object context the merge will sometimes 
delete part of one side of the relationship. This happens with many-to-
many relationships including reflexive). By calling 
refreshObject:mergeChanges: I am forcing that object to be faulted and 
re-fetched with the correct data in the store.

It seems that sometimes the call to 
mergeChangesFromContextDidSaveNotification: causes an error that shows 
up in the output as "statement is still active". It appears that 
object controllers that are bound to a managed object context receive 
a notification "_NSObjectsChangedInManagingContextPrivateNotification" 
and they do some fetching and the error occurs when they do a fetch 
request.

I ran with the Core Data threading assertions in the _debug version of 
the library and nothing special is reported.

Has anyone encountered this problem before and found a solution?

--
Michael

Related mailsAuthorDate
mlCore Data merge and "statement is still active" error? Michael Link Jun 3, 22:37
mlre: Core Data merge and "statement is still active" error? Ben Trumbull Jun 4, 00:52
mlRe: Core Data merge and "statement is still active" error? Michael Link Jun 4, 02:15
mlRe: Core Data merge and "statement is still active" error? Ben Trumbull Jun 5, 23:37
mlRe: Core Data merge and "statement is still active" error? Michael Link Jun 6, 01:49
mlRe: Core Data merge and "statement is still active" error? Ben Trumbull Jun 6, 04:01