Reputation: 53
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:
cancelAllOperations
& waitUntilAllOperationsAreFinished
on the queue that the performBlocks
are implementedmaxConcurrentOperationCount = 1
on the queue of the performBlocks
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
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
Reputation: 16684
You need to reset managedObjectContext
which was used before this operation.
Call managedObjectContext.reset()
Upvotes: 7
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
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