nick3389
nick3389

Reputation: 53

Core data crash when resetting the store: 'Object's persistent store is not reachable from this NSManagedObjectContext's coordinator'

I get a crash when trying to delete the persistent store of Core data in my iOS app written in Swift. The flow is straight forward: When I log out from the app I delete the store with:

destroyPersistentStoreAtURL

I use native Core Data implementation in the application and every access to a managed object is made with performBlock/performBlockAndWait. Also, these operations are in a NSOperationQueue. The flow is the following:

  1. Log out
  2. cancelAllOperations & waitUntilAllOperationsAreFinished on the queue that the performBlocks are implemented
  3. maxConcurrentOperationCount = 1 on the queue of the performBlocks
  4. Finally, I add an operation which destroys the persistent store in the previous NSOperationQueue

Sometimes, I get a crash and I cannot understand why. From what I see, it is something related with managedObjectsIDs and retain. Take a look:

2016-11-14 15:51:58.053 ******[3912:179074] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Object's persistent store is not reachable from this NSManagedObjectContext's coordinator'
*** First throw call stack:
(
	0   CoreFoundation                      0x000000010ca0f34b __exceptionPreprocess + 171
	1   libobjc.A.dylib                     0x000000010c05321e objc_exception_throw + 48
	2   CoreData                            0x000000010c5683b2 _PFRetainedObjectIDCore + 1074
	3   CoreData                            0x000000010c5507fc -[NSManagedObjectContext objectWithID:] + 668
	4   CoreData                            0x000000010c590264 _faultBatchAtIndex + 1524
	5   CoreData                            0x000000010c59217a -[_PFBatchFaultingArray retainedObjectAtIndex:] + 74
	6   CoreData                            0x000000010c592262 -[_PFBatchFaultingArray objectAtIndex:] + 50
	7   CoreData                            0x000000010c67d9de __72-[NSFetchedResultsController(PrivateMethods) _computeSectionInfo:error:]_block_invoke + 190
	8   CoreData                            0x000000010c55adc7 developerSubmittedBlockToNSManagedObjectContextPerform + 199
	9   CoreData                            0x000000010c55ac7f -[NSManagedObjectContext performBlockAndWait:] + 255
	10  CoreData                            0x000000010c67d3b6 -[NSFetchedResultsController(PrivateMethods) _computeSectionInfo:error:] + 694
	11  CoreData                            0x000000010c681d75 __82-[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:]_block_invoke + 1077
	12  CoreData                            0x000000010c55adc7 developerSubmittedBlockToNSManagedObjectContextPerform + 199
	13  CoreData                            0x000000010c55ac7f -[NSManagedObjectContext performBlockAndWait:] + 255
	14  CoreData                            0x000000010c681927 -[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:] + 119
	15  CoreFoundation                      0x000000010c9ad19c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
	16  CoreFoundation                      0x000000010c9ad09b _CFXRegistrationPost + 427
	17  CoreFoundation                      0x000000010c9ace02 ___CFXNotificationPost_block_invoke + 50
	18  CoreFoundation                      0x000000010c96fea2 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 2018
	19  CoreFoundation                      0x000000010c96ef3b _CFXNotificationPost + 667
	20  Foundation                          0x000000010bb1b0ab -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
	21  CoreData                            0x000000010c5432b0 -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 704
	22  CoreData                            0x000000010c562b50 -[NSManagedObjectContext(_NSInternalNotificationHandling) _processChangedStoreConfigurationNotification:] + 2976
	23  CoreData                            0x000000010c5d97ed __95-[NSManagedObjectContext(_NSInternalNotificationHandling) _sendOrEnqueueNotification:selector:]_block_invoke + 109
	24  CoreData                            0x000000010c55adc7 developerSubmittedBlockToNSManagedObjectContextPerform + 199
	25  libdispatch.dylib                   0x000000010e0250cd _dispatch_client_callout + 8
	26  libdispatch.dylib                   0x000000010e0058d6 _dispatch_main_queue_callback_4CF + 406
	27  CoreFoundation                      0x000000010c9d34f9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
	28  CoreFoundation                      0x000000010c998f8d __CFRunLoopRun + 2205
	29  CoreFoundation                      0x000000010c998494 CFRunLoopRunSpecific + 420
	30  GraphicsServices                    0x000000010f5d0a6f GSEventRunModal + 161
	31  UIKit                               0x000000010a050964 UIApplicationMain + 159
	32  ******                              0x000000010817e932 main + 114
	33  libdyld.dylib                       0x000000010e07168d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Any help is much appreciated!

Upvotes: 3

Views: 4046

Answers (4)

berbie
berbie

Reputation: 1028

I had the same issue and Tom's hint assuming that dirty objects — that used to live in the old store — where still part of the managed object context after I removed the persistent store from the coordinator. In my case I implemented a "revert to last saved document version" which needs to make sure that these dirty objects are being discarded first.

[_managedObjectContext reset]
[_managedObjectContext.persistentStoreCoordinator removePersistentStore:_store error:outError]

If you still have references to these objects in your code, object.managedObjectContext will be nil — which is a good hint to recover.

Upvotes: 2

Shmidt
Shmidt

Reputation: 16684

You need to reset managedObjectContext which was used before this operation.

Call managedObjectContext.reset()

Upvotes: 7

nick3389
nick3389

Reputation: 53

@Tom

Yes, you are right. So I post you an example:

let queue = NSOperationQueue

queue.addOperationWithBlock{
  let moc = newPrivateQueueManagedObjectContext()
  moc.performBlock {
    //some work to do on the context
}

and then sometime I destroy the store, but before that I cancel the operations on the above queue. Still, sometimes I see a crash...

Upvotes: 0

Tom Harrington
Tom Harrington

Reputation: 70986

The error is telling you that you're still trying to use a managed object after you have destroyed the persistent store from which it was fetched. That's guaranteed to cause exactly this crash.

It's impossible to say exactly where this is happening, but if you keep any reference to a managed object after removing the store, you'll get this. Cancelling operations, using performBlock, etc, don't make any difference if at the end you're still trying to use a managed object that doesn't have a persistent store any more.

Upvotes: 2

Related Questions