核心数据崩溃 NSInternalInconsistencyException 'statement is still active'
Core Data crash NSInternalInconsistencyException 'statement is still active'
我有两个共享同一个持久存储协调器的托管对象上下文:
- 主线程
NSMainQueueConcurrencyType
和
- 一个
NSPrivateQueueConcurrencyType
用于后台处理。
所有数据解析工作都发生在针对私有队列的 performBlock 调用中,并通过 NSManagedObjectContextDidSaveNotification
合并到主线程上进行 UI 更新。
我启用了 Core Data 多线程断言,它们在崩溃发生时从不触发。
当我在后台上下文工作时推入具有 NSFetchedResultsController
的新视图时,我偶尔会遇到崩溃,显示 statement is still active
。崩溃将在获取结果控制器的获取时触发,或者在存储数据的代码中触发。当它在数据解析部分崩溃时,它总是在一对多关系中失败。
这些崩溃是 100% iOS 8 到目前为止,我从未在 7 上看到过它们。
我的问题是: 假设我没有违反线程限制(断言应该大声喊叫,但没有......)还有其他明显的事情吗我可能这样做会导致主线程上下文在后台线程正在持久存储上工作时崩溃?
Crashlytics 是这样说的:
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)
您可以使用 nsmanaged 对象上下文的副本作为 nsmanagedobject 上下文的新实例。
对于每个托管对象上下文,您应该像这样使用您想要在多线程中保存不一致的地方
[backgroundMOC performBlockAndWait:^{
// read/write operation
[backgroundMOC saveContextWithMOC:backgroundMOC];
}];
// 主线程 MOC
[mainMOC performBlockAndWait:^{
// read/write operation
[backgroundMOC saveContextWithMOC:backgroundMOC];
}];
我最终改变了我创建核心数据堆栈的方式,这就消失了。移动到持久存储上下文、子 UI 上下文和孙子背景上下文并适当地在链上持久化使这一切变得更好。我仍然不是 100% 确定为什么原始设置不适用于 8。
我有两个共享同一个持久存储协调器的托管对象上下文:
- 主线程
NSMainQueueConcurrencyType
和 - 一个
NSPrivateQueueConcurrencyType
用于后台处理。
所有数据解析工作都发生在针对私有队列的 performBlock 调用中,并通过 NSManagedObjectContextDidSaveNotification
合并到主线程上进行 UI 更新。
我启用了 Core Data 多线程断言,它们在崩溃发生时从不触发。
当我在后台上下文工作时推入具有 NSFetchedResultsController
的新视图时,我偶尔会遇到崩溃,显示 statement is still active
。崩溃将在获取结果控制器的获取时触发,或者在存储数据的代码中触发。当它在数据解析部分崩溃时,它总是在一对多关系中失败。
这些崩溃是 100% iOS 8 到目前为止,我从未在 7 上看到过它们。
我的问题是: 假设我没有违反线程限制(断言应该大声喊叫,但没有......)还有其他明显的事情吗我可能这样做会导致主线程上下文在后台线程正在持久存储上工作时崩溃?
Crashlytics 是这样说的:
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)
您可以使用 nsmanaged 对象上下文的副本作为 nsmanagedobject 上下文的新实例。 对于每个托管对象上下文,您应该像这样使用您想要在多线程中保存不一致的地方
[backgroundMOC performBlockAndWait:^{
// read/write operation
[backgroundMOC saveContextWithMOC:backgroundMOC];
}];
// 主线程 MOC
[mainMOC performBlockAndWait:^{
// read/write operation
[backgroundMOC saveContextWithMOC:backgroundMOC];
}];
我最终改变了我创建核心数据堆栈的方式,这就消失了。移动到持久存储上下文、子 UI 上下文和孙子背景上下文并适当地在链上持久化使这一切变得更好。我仍然不是 100% 确定为什么原始设置不适用于 8。