核心数据保存竞争条件错误

时间:2011-05-17 17:59:13

标签: multithreading ios core-data concurrency

我有一个NSOperation来更新应用数据。此操作具有自己的上下文,并通过contextDidSave通知将更改传递回主线程上下文。

更新操作会删除对象。这些删除无意中导致崩溃。当主线程在保存更新上下文的同时重新加载UITableView时发生崩溃。 tableview的数据源由NSFetchedResultsController支持。

CoreData或UIKit都不输出任何记录。崩溃是在访问managedObject的属性时tableView:cellForRowAtIndexPath:中发生的SIG_ABRT。这是成功更新的结果。您可以看到该表填充一次,然后保存上下文,从而导致表重新加载:

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

stacktrace

我可以想到两个可能的解决方案:

  1. 在表格视图刷新时锁定persitentStoreCoordinator。 (这可以通过继承UITableView并覆盖reloadData以提供锁定和解锁商店的位置来完成。
  2. 将删除推迟到以后的日期,例如,当应用程序退出时。 (这可以通过向实体添加isStale attrib或通过创建新的Trash实体并向其添加对象来完成。)
  3. 但是,这两种解决方案看起来都非常糟糕。我错过了什么吗?我的第一个尝试是尝试使NSFetchedResultsController预取所有对象,但这是不可能的。另一种可能的解决方案是在使用controllerDidChangeContent:时锁定存储,但是当fetchedResultsController未触发表重新加载时仍会出现问题。

1 个答案:

答案 0 :(得分:0)

正如其他人所说,堆栈跟踪至关重要。没有我们只能猜测解决方案。