问题
My UITableView is scrolling up once I add a new comment to CoreData. NSFetchedResultsController knows about it, puts this comment at the bottom of the table, and scroll table to top. Is it normal?
My example:
Just before I add a comment:
Just after I add a comment (not expected behavior):
It should be just like this (after I swipe it by hand manually):
This may be connected with following situation:
This is sort descriptor of my
NSFetchedResultsController:NSSortDescriptor(key: "createdAt", ascending: false) //from the latest to the oldestBut I need to display my comments for reversed index paths (the latest are at the very bottom). In other words, everywhere when I need to use
indexPathI use:private func reversedIndexPathForIndexPath(indexPath: NSIndexPath) -> NSIndexPath { return NSIndexPath(forRow: fetchedResultsController.fetchedObjects!.count - indexPath.row - 1, inSection: 0) }
NSFetchedResultsControllerDelegate:
//MARK: - NSFetchedResultsControllerDelegate
func controllerWillChangeContent(controller: NSFetchedResultsController) {
self.tableView.beginUpdates()
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
if let newIndexPath = newIndexPath {
tableView.insertRowsAtIndexPaths([reversedIndexPathForIndexPath(newIndexPath)], withRowAnimation: .Fade)
}
case .Delete:
if let indexPath = indexPath {
tableView.deleteRowsAtIndexPaths([reversedIndexPathForIndexPath(indexPath)], withRowAnimation: .Fade)
}
case .Update:
if let indexPath = indexPath {
tableView.reloadRowsAtIndexPaths([reversedIndexPathForIndexPath(indexPath)], withRowAnimation: .Fade)
}
case .Move:
if let indexPath = indexPath, let newIndexPath = newIndexPath {
tableView.deleteRowsAtIndexPaths([reversedIndexPathForIndexPath(indexPath)], withRowAnimation: .Fade)
tableView.insertRowsAtIndexPaths([reversedIndexPathForIndexPath(newIndexPath)], withRowAnimation: .Fade)
}
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
tableView.endUpdates()
}
Is it connected to my problem?
回答1:
Edited answer:
I was able to reproduce this glitch with the following steps:
UITableViewwith itsrowHeightset toUITableViewAutomaticDimensionand non-zeroestimatedRowHeight.- Table scrolled to its very bottom, with the last cell fully visible at the bottom margin.
- Inserting the new cell below the last one results in visual shift of the cells a few points down (in my setup it differs from 5 to 40).
The source of this behavior needs additional investigation.
For now the only solution is not to use UITableViewAutomaticDimension and return row heights from tableView:heightForRowAtIndexPath:.
By the way, implementation of inverted index paths has one significant flaw. When FRC calls it's delegate method controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:, all deletion index paths belongs to pre-change data set, and all insertion index paths - to post-change one. When you are in-beetween controllerWillChangeContent: and controllerDidChangeContent:, fetchedResultsController.fetchedObjects will contain post-change data set, i suppose (needs to be checked, though).
回答2:
I found something that worked for me. I encountered the same problem, and my estimatedRowHeight was 33 and all of my cells are greater than 33.
I just changed my estimatedRowHeight to my maximum cell height(or greater than your maximum cell height)
self.table.estimatedRowHeight = 310
self.table.rowHeight = UITableViewAutomaticDimension
worked like a charm, all cells are now autoresizing and uitableview is not scrolling to top or bottom when core data performs an update/delete/insert
来源:https://stackoverflow.com/questions/33012157/how-to-prevent-from-scrolling-uitableview-up-when-nsfetchedresultscontroller-add