I've got a simple usage of NSFetchedResultsController defined something like this contrived example
let request: NSFetchRequest<StudentEntity> = StudentEntity.fetchRequest()
request.sortDescriptors = [
NSSortDescriptor(key: "class.name", ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:)))
]
fetchedResultsController = NSFetchedResultsController<StudentEntity>(
fetchRequest: request,
managedObjectContext: context,
sectionNameKeyPath: "class.name",
cacheName: nil)
Which helps a table view to display student entities grouped into sections by the class they have set in their class relationship. The class entity has a name attribute so that the sectionNameKeyPath is class.name.
When the user makes an edit to a class referenced by a student I try to reload the data in the table but unfortunately I was finding that the section name I was working with was NOT updating. Lots of debugging reveals that the class entity is of course updating fine, but for some reason the sections[].name is not updating. I update the class name as follows
classEntity.name = newClassName
do
{
try context.save()
}
catch let error
{
dbgLog("failed to save context; error=\(error)")
}
tableView.reloadData();
Which causes the following data source method to correctly run
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let sectionInfo = fetchedResultsController!.sections![section]
let sectionTitle = sectionInfo.name
let sectionStudentEntity = sectionInfo.objects![0] as! StudentEntity
let sectionTitleFromStudent = sectionStudentEntity.class!.name!
however the sectionTitle will NOT be updated and show the old class name, where as the sectionTitleFromStudent correctly shows the updated new class name.
I'm presuming this is because the sectionNameKeyPath is a nested path and somehow although the class entity is updating, the fetchedResultsController somehow doesn't detect any changes in the student entities themselves and so doesn't recreate these section names. Feels like a bug, but thankfully I can work around it by using the correctly updated sectionTitleFromStudent string.
Anyone got any ideas, or has come across the same issue themselves?
Cheers
The FetchedResultsController will only observe changes to objects for the entity underlying its fetch (in your case Student
objects). So it is unaware of the change to the attributes of the related Class
objects. To make it aware, you can redo the performFetch
which should trigger it to update its fetched objects and sections. (Note that performFetch
bypasses the normal FRC change tracking, so the FRC delegate methods will not fire, but that should not be a problem since you are doing a complete reloadData
on the tableView anyway).