Reputation: 4962
I am using the following method to update my tableView when new entities are created, using the fetchedResultsController delegate:
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .insert:
//Crash here
self.tableView.insertRows(at: [newIndexPath!], with: .automatic)
default:
print("default")
}
}
This works, but sometimes I am getting the following crash:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0.
The number of rows contained in an existing section after the update (6) must be equal to the number of rows contained in that section before the update (0), 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). *** First throw call stack:
Im am using a fetchedResultsController. I did some research and the answers claim to update the numberOfRowsInSection, but I have the number of rows in the section set to the number of objects in the fetchedResultController section. I tried calling reloadData() after & before insertingRows but this does not fix it. Here is my numberOfRowsInSection method:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let sections = fetchedResultsController.sections {
let currentSection = sections[section]
return currentSection.numberOfObjects
}
return 0
}
And my fetchedResultsController:
lazy var fetchedResultsController: NSFetchedResultsController<Project> = {
let userFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Project")
let coreDataStack = CoreDataStack.default()
let managedContext = coreDataStack?.managedObjectContext
let primarySortDescriptor = NSSortDescriptor(key: "dateCreated", ascending: false)
userFetchRequest.sortDescriptors = [primarySortDescriptor]
let frc = NSFetchedResultsController(
fetchRequest: userFetchRequest,
managedObjectContext: managedContext!,
sectionNameKeyPath: nil,
cacheName: nil)
frc.delegate = self
return frc as! NSFetchedResultsController<Project>
}()
//SOLUTION:
This is what I had to do to fix the issue, as mentioned by Zepar.
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.tableView.endUpdates()
}
Upvotes: 2
Views: 387
Reputation: 165
You'd forgotten to inform tableView that the content was started updating:
[self.tableView beginUpdates];
and
[self.tableView endUpdates];
The number of modified sections and rows have to be consistent with the fetched ones.
Look into the documentation, there is an example as well: https://developer.apple.com/reference/coredata/nsfetchedresultscontrollerdelegate
Upvotes: 2