代码 :
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if let sections = fetchedResultsController.sections {
return sections.count
}
return 0
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let sections = fetchedResultsController.sections {
let sectionInfo = sections[section]
return sectionInfo.numberOfObjects + 3
}
return 3
}
func controllerWillChangeContent(controller: NSFetchedResultsController) {
print("controllerWillChangeContent")
self.tableView.beginUpdates()
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
print("controllerDidChangeContent")
self.tableView.endUpdates()
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
print("didChangeObject: \(indexPath?.row), \(newIndexPath?.row)")
var _indexPath, _newIndexPath: NSIndexPath?
if let path = indexPath {
_indexPath = NSIndexPath(forRow: path.row + 3, inSection: path.section)
}
if let path = newIndexPath {
_newIndexPath = NSIndexPath(forRow: path.row + 3, inSection: path.section)
}
switch type {
case .Insert:
print("insert: \(_indexPath?.row), \(_newIndexPath?.row), \(self.fetchedResultsController.sections?[0].numberOfObjects)")
self.tableView.insertRowsAtIndexPaths([_indexPath!], withRowAnimation: .Fade)
break
case .Update:
print("update: \(_indexPath?.row), \(_newIndexPath?.row)")
self.tableView.reloadRowsAtIndexPaths([_indexPath!], withRowAnimation: .Fade)
break
case .Delete:
print("delete: \(_indexPath?.row), \(_newIndexPath?.row)")
self.tableView.deleteRowsAtIndexPaths([_indexPath!], withRowAnimation: .Fade)
break
case .Move:
print("move: \(_indexPath?.row), \(_newIndexPath?.row)")
if _indexPath?.row != _newIndexPath?.row {
self.tableView.moveRowAtIndexPath(_indexPath!, toIndexPath: _newIndexPath!)
}
break
}
}
每行都有一个按钮。该按钮上的点击事件会触发NSManagedObjectContext
中的更新:
chat?.managedObjectContext?.performBlockAndWait({
let mutableData = chat?.data?.mutableCopy() as? NSMutableDictionary
mutableData?.setObject(true, forKey: "isAnswered")
chat?.data = mutableData?.copy() as? NSDictionary
do {
if chat?.managedObjectContext?.hasChanges == true {
try chat?.managedObjectContext?.save()
}
} catch {
print("Unable to save: \(error)")
}
})
场景1: 当列表中的最后一个NSManagedObject
有任何更新时(有NSManagedObject
+ 3 {{1} s),日志如下:
String
场景2: 当除了最后一行之外的其他行中有controllerWillChangeContent
didChangeObject: Optional(328), nil
update: Optional(331), nil
didChangeObject: Optional(328), Optional(328)
insert: Optional(331), Optional(331), Optional(329)
controllerDidChangeContent
*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit/UIKit-3347.44.2.2/UITableView.m:1406
CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. attempt to insert row 332 into section 0, but there are only 332 rows in section 0 after the update with userInfo (null)
时,日志为:
update
问题:
controllerWillChangeContent
didChangeObject: Optional(325), nil
update: Optional(328), nil
didChangeObject: Optional(325), Optional(325)
insert: Optional(328), Optional(328), Optional(329)
controllerDidChangeContent
*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit/UIKit-3347.44.2.2/UITableView.m:1623
CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (332) must be equal to the number of rows contained in that section before the update (332), plus or minus the number of rows inserted or deleted from that section (2 inserted, 1 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)
时,为什么NSFetchedResultsController
会触发update
+ insert
?