How to Prevent from Scrolling Uitableview Up When Nsfetchedresultscontroller Add New Record

How to prevent from scrolling UITableView up when NSFetchedResultsController add new record?

Edited answer:

I was able to reproduce this glitch with the following steps:

  1. UITableView with its rowHeight set to UITableViewAutomaticDimension and non-zero estimatedRowHeight.
  2. Table scrolled to its very bottom, with the last cell fully visible at the bottom margin.
  3. 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).

NSFetchedResultsController and scrollToBottom in Table

Don't scroll, just set the content offset without animation. At minimum the height of each cell needs to be determined but the cell itself doesn't need to be loaded for every row.

Note that most apps which display in this way won't have all old messages in the immediate history, they'll only have a couple of pages, and if you scroll up too far they'll need to go and load those older messages. This approach bounds and loading issues.

Make UITableView keep scroll position when adding cells at top

Ok, after some responses which pointed me in right direction I came up with this solution. It works smooth though does some ugly coordinates math and doesn't support different cell sizes. Hope it will be helpful for someone.

-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
NSIndexPath *firstVisible = [[self.tableView indexPathsForVisibleRows] firstObject];
self.topVisibleMessage = [self.fetchedResultsController objectAtIndexPath:firstVisible];

NSIndexPath *topIndexPath = [self.fetchedResultsController indexPathForObject:self.topVisibleMessage];

self.cellOffset = self.tableView.contentOffset.y - topIndexPath.row * [self firstRowHeight];
}

-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView reloadData];

if (self.topVisibleMessage) {
NSIndexPath *topIndexPath = [self.fetchedResultsController indexPathForObject:self.topVisibleMessage];
CGPoint point = {0, topIndexPath.row * [self firstRowHeight] + self.cellOffset};

[self.tableView setContentOffset:point];
}
}

Issues when inserting multiple rows into a tableView using NSFetchedResultsController delegate methods

Since my cell heights are dynamic, I was setting the estimatedRowHeight to 300, changing it to 1000 seemed to fix my problem. If you know of any other way to fix it besides this, or any improvement to my code, let me know. Thanks

This is what lead me to my answer.
https://stackoverflow.com/a/38867302/4745553

EDIT

I actually was still having an issue and since I was responding to multiple changes, I was just using the controllerDidChangeContent delegate method and called tableView.reloadData() in their. Their is no animation but that's okay with what I'm doing.

This helped me fix it as well. https://stackoverflow.com/a/3013353/4745553



Related Topics



Leave a reply



Submit