I have two managed object contexts that share the same persistent store coordinator:
NSMainQueueConcurrencyType
for the main thread and NSPrivateQueueConcurrencyType
for doing background processing. All data parsing work happens in performBlock calls against the private queue and are merged in via NSManagedObjectContextDidSaveNotification
for UI updates on the main thread.
I have Core Data Multithreading assertions enabled, and they never trigger when the crash occurs.
I will occasionally get a crash that says statement is still active
when I push in a new view that has a NSFetchedResultsController
while the background context is working. The crash will either trigger on the fetch for the fetched results controller or within the code that is storing data. When it crashes in the data parsing section it always fails at a to-many relationship.
These crashes are 100% iOS 8 so far and I've never seen them on 7.
My question is this: assuming that I am not violating thread confinement (which the assertion should yell loudly about, and hasn't...) is there anything else obvious that I could be doing that would cause the main thread context to bomb out while the background thread is in the process of doing work on the persistent store?
Here's what Crashlytics says:
Thread : Fatal Exception: NSInternalInconsistencyException
0 CoreFoundation 0x00000001871e659c __exceptionPreprocess + 132
1 libobjc.A.dylib 0x00000001978f00e4 objc_exception_throw + 60
2 CoreData 0x0000000186e97c6c -[NSSQLiteStatement cachedSQLiteStatement]
3 CoreData 0x0000000186e9739c -[NSSQLiteConnection prepareSQLStatement:] + 76
4 CoreData 0x0000000186eb3810 -[NSSQLChannel selectRowsWithCachedStatement:] + 76
5 CoreData 0x0000000186f9e7a4 newFetchedRowsForFetchPlan_MT + 1100
6 CoreData 0x0000000186ecf948 -[NSSQLCore newFetchedPKsForSourceID:andRelationship:] + 2120
7 CoreData 0x0000000186ecea24 -[NSSQLCore newValueForRelationship:forObjectWithID:withContext:error:] + 616
8 CoreData 0x0000000186f67480 __110-[NSPersistentStoreCoordinator(_NSInternalMethods) newValueForRelationship:forObjectWithID:withContext:error:]_block_invoke + 80
9 CoreData 0x0000000186f6d654 gutsOfBlockToNSPersistentStoreCoordinatorPerform + 180
10 CoreData 0x0000000186f60ccc _perform + 204
11 CoreData 0x0000000186ece730 -[NSPersistentStoreCoordinator(_NSInternalMethods) newValueForRelationship:forObjectWithID:withContext:error:] + 160
12 CoreData 0x0000000186ece4d8 -[NSFaultHandler retainedFulfillAggregateFaultForObject:andRelationship:withContext:] + 716
13 CoreData 0x0000000186ef15ec -[_NSFaultingMutableSet willReadWithContents:] + 444
14 CoreData 0x0000000186ed146c -[_NSFaultingMutableSet count] + 32
15 CoreData 0x0000000186ecd234 -[NSManagedObject(_NSInternalMethods) _didChangeValue:forRelationship:named:withInverse:] + 440
16 Foundation 0x0000000187fe1a14 NSKeyValueNotifyObserver + 340
17 Foundation 0x0000000187fe1534 NSKeyValueDidChange + 460
18 Foundation 0x0000000187fcaac4 -[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 116
19 CoreData 0x0000000186ec4e90 _PF_ManagedObject_DidChangeValueForKeyIndex + 140
20 CoreData 0x0000000186ec3248 _sharedIMPL_setvfk_core + 284
21 My App 0x00000001000f0b00 -[LocationAdapter processBuildingList:context:completion:] (LocationAdapter.m:134)
I ended up changing around how I created the core data stack and this went away. Moving to a persistent store context, a child UI context, and a grandchild background context and persisting up the chain appropriately made this all better. I'm still not 100% sure why the original setup did not work with 8.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With