Multithreading 核心数据保存竞争条件错误
我有一个更新应用程序数据的Multithreading 核心数据保存竞争条件错误,multithreading,ios,core-data,concurrency,Multithreading,Ios,Core Data,Concurrency,我有一个更新应用程序数据的NSOperation。此操作有自己的上下文,更改通过contextDidSave通知传回主线程上的上下文 更新操作删除对象。这些删除操作无意中导致了崩溃。当主线程在保存更新上下文的同时重新加载UITableView时,会发生崩溃。tableview的数据源由一个NSFetchedResultsController支持 CoreData或UIKit均未输出任何日志记录。崩溃是在访问managedObject的属性时在tableView:cellForRowAtIndex
NSOperation
。此操作有自己的上下文,更改通过contextDidSave
通知传回主线程上的上下文
更新操作删除对象。这些删除操作无意中导致了崩溃。当主线程在保存更新上下文的同时重新加载UITableView
时,会发生崩溃。tableview的数据源由一个NSFetchedResultsController
支持
CoreData或UIKit均未输出任何日志记录。崩溃是在访问managedObject的属性时在tableView:cellForRowAtIndexPath:
中发生的信号。以下是成功更新的结果。您可以看到,表格被填充一次,然后上下文被保存,这又导致表格被重新加载:
tableView:numberOfRowsInSection: rowCount = 29
tableView:cellForRowAtIndexPath: row: 0
tableView:cellForRowAtIndexPath: row: 1
tableView:cellForRowAtIndexPath: row: 2
tableView:cellForRowAtIndexPath: row: 3
tableView:cellForRowAtIndexPath: row: 4
tableView:cellForRowAtIndexPath: row: 5
tableView:cellForRowAtIndexPath: row: 6
tableView:cellForRowAtIndexPath: row: 7
tableView:cellForRowAtIndexPath: row: 8
tableView:cellForRowAtIndexPath: row: 9
Will saved update context
Did saved update context
Will merge update context
tableView:numberOfRowsInSection: rowCount = 58
Did merge update context
tableView:numberOfRowsInSection: rowCount = 29
tableView:cellForRowAtIndexPath: row: 0
tableView:cellForRowAtIndexPath: row: 1
tableView:cellForRowAtIndexPath: row: 2
tableView:cellForRowAtIndexPath: row: 3
tableView:cellForRowAtIndexPath: row: 4
tableView:cellForRowAtIndexPath: row: 5
tableView:cellForRowAtIndexPath: row: 6
tableView:cellForRowAtIndexPath: row: 7
tableView:cellForRowAtIndexPath: row: 8
tableView:cellForRowAtIndexPath: row: 9
下面是崩溃发生时的输出:
tableView:numberOfRowsInSection: rowCount = 29
tableView:cellForRowAtIndexPath: row: 0
tableView:cellForRowAtIndexPath: row: 1
tableView:cellForRowAtIndexPath: row: 2
Will saved update context
tableView:cellForRowAtIndexPath: row: 3
tableView:cellForRowAtIndexPath: row: 4
tableView:cellForRowAtIndexPath: row: 5
我可以想出两种可能的解决办法:
UITableView
并覆盖reloadData
来实现,以提供锁定和解锁存储的位置)isStale
attrib或创建新的Trash
实体并向其添加对象来实现。)然而,这两种解决方案似乎都非常粗糙。我错过什么了吗?我的第一个想法是尝试让
NSFetchedResultsController
预取所有对象,但这是不可能的。另一种可能的解决方案是在使用控制器idchangeContent:
时锁定存储,但当fetchedResultsController未触发表重新加载时,仍然会出现问题。正如其他人提到的,堆栈跟踪是至关重要的。如果没有,我们只能猜测解决方案。@Benedict Cohen控制台和stacktrace上的崩溃显示了什么?你确定你做得对吗?“此操作有自己的上下文,更改会通过contextDidSave通知传回主线程上的上下文。”这部分内容看起来特别狡猾,我已经仔细检查过了,我99%确定我做得对。我已经使用通知和mergeChangesFromContextDidSaveNotification的文档在其他线程中读取并重新读取了跟踪更改:@Benedict Cohen你看过CoreDataBooks的例子吗?似乎有两个陷阱很容易忘记或错过。。此外,您是否在表视图中使用beginUpdate/endUpdate?@Benedict Cohen SIG_ABRT还建议过早释放对象。是否可能有其他对象持有对已删除对象的引用,或已删除对象持有对某个对象的无效引用?从我所看到的情况来看,如果上下文合并失败,您应该得到InternalConsistency异常,而不是SIG_ABRT(我不是100%确定,但值得检查)