Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data - deadlock while removing persistent store

Tags:

ios

core-data

Is there a safe way to remove the persistent store (and create a new one) in an application, where other threads are using NSManagedObjectContext's associated with the store being removed? I have tried locking the NSPersistentStoreCoordinator and unlocking it after the operation is over, but it didn't help - all my attempts have resulted in a deadlock. It always happens on this line (executed on the main thread):

[self.persistentStoreCoordinator removePersistentStore: store error: &error];
like image 518
Marcin Kuptel Avatar asked Jan 19 '13 17:01

Marcin Kuptel


2 Answers

I haven't tried this, but from the docs on moc setPersistentStoreCoordinator: ...

The coordinator provides the managed object model and handles persistency. Note that multiple contexts can share a coordinator.

This method raises an exception if coordinator is nil. If you want to “disconnect" a context from its persistent store coordinator, you should simply set all strong references to the context to nil and allow it to be deallocated normally.

This would suggest that the safe way to remove the psc is to first have every thread with a moc release it (nil-out reference to it in ARC), then perform the removePersistentStore:

like image 136
danh Avatar answered Oct 25 '22 14:10

danh


I would try using an approach described here (section Parent/Child Contexts): Multi-Context CoreData

Basically, your PSC has only one MOC associated with it (the parent MOC). Other threads have their own MOCs, with their parentContext set to the main MOC (the one associated with the PSC).

Then you could try something like this:

// Save each child MOC
for (NSManagedObjectContext *moc in self.someChildMOCs)
{
   [moc performBlockAndWait:^{

       // push to parent
       NSError *error;
       NSAssert([moc save:&error]);
       moc.parentContext = nil;
   }];
}

// Save parent MOC to disk
[self.mainMOC performBlockAndWait:^{
   NSError *error;
   NSAssert([mainMOC save:&error]);
}];

[self.persistentStoreCoordinator removePersistentStore:store error:&error];
mainMOC.persistentStoreCoordinator = nil;
like image 1
Norbert Avatar answered Oct 25 '22 13:10

Norbert