我有多个核心数据实体,全部同步到服务器。为了进行测试,我构建了一个函数,它将: 1.删除所有核心数据实体 2.调用API刷新所有数据
// Next delete data in all entities (but not user)
for entity in CoreDataStack.sharedInstance.allEntities() {
if (entity != "User") {
if (DataAccess.deleteExisting(entityName: entity, inMoc: self.operationMOC)) {
print("Deleted OK: \(entity)")
} else {
print("ERROR deleting \(entity)")
}
}
}
....
// Save updates
self.operationMOC.performAndWait {
do {
try self.operationMOC.save()
} catch {
fatalError("ERROR: Failed to save operation moc: \(error)")
}
}
self.mainThreadMOC.performAndWait {
do {
try self.mainThreadMOC.save()
} catch {
fatalError("ERROR: Failed to save main moc: \(error)")
}
}
问题是控制我的 UI 的 NSFetchedResultsController 似乎无法识别删除,当“didChange”委托(delegate)方法触发更新时给出错误
error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (14) must be equal to the number of rows contained in that section before the update (7), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null)
我已将刷新功能分成两部分,这样我就可以看到删除从未被识别,因此当更新触发并尝试 tableView.insertRows(at: ...) 时,UITableView 行太多。 我还尝试在我的主线程上直接更新 MOC - 不走运
我还放了一个观察者:
NotificationCenter.default.addObserver(self, selector: #selector(MessagesTab.dataChanged), name: NSNotification.Name.NSManagedObjectContextObjectsDidChange, object: self.mainThreadMOC)
它在删除和更新时完美触发,所以 Core Data 正在做它的工作。
因此,在我转储 NSFetchResults Controller 并使用通知滚动我自己之前,我的问题是有人知道我在这里做错了什么吗? (在代码或期望中) 在过去的一天里,我一直对此感到困惑,因此我们将不胜感激地收到任何建议。
我的 NSFetchedResultsControllerDelegate didChange 方法:
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
print(">>>> FRC Change Fired")
switch type {
case .insert:
tableView.insertRows(at: [newIndexPath!], with: .automatic)
case .delete:
tableView.deleteRows(at: [indexPath!], with: .automatic)
case .update:
let rowMessage = self.fetchedResultsController.object(at: indexPath!)
if let cell = self.tableView.cellForRow(at: indexPath!) as? InterestsListCell {
cell.configureWithData(rowMessage)
}
default:
print("Was not a update, delete or insert")
}
}
最佳答案
非常感谢@JonRose 此代码不会导致 FRC 触发
// Delete all records for the entity
func deleteExisting(entityName: String, inMoc moc: NSManagedObjectContext) -> Bool {
do {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
let deleteRequest = NSBatchDeleteRequest(fetchRequest: request)
try moc.execute(deleteRequest)
return true
} catch {
print("ERROR: deleting existing records - \(entityName)")
return false
}
}
随后我对此进行了研究,希望它能帮助其他人 - 参见 WWDC 2015 session on Core Data显示此幻灯片的位置: 我尝试过使用 .refreshAll() 和 .mergeChages,但对我来说最简单的似乎是放弃我的 FRC 并使用 NSManagedObjectContextDidSave 通知
关于ios - NSFetchedResultsController 无法识别删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43610719/