Edit: https://streamable.com/rfym will show it in action. The first time I press Scroll To Bottom, it doesn't get all the way to the bottom. I then manually get all the way to the bottom and quickly scroll all the way back up. Once I press Scroll To Bottom again, it works correctly because it is using the cachedHeights.
So, I've seen many answers for this, but none of them seem to work for me and I'm pretty sure these doesn't work for many others as well:
tableView.setContentOffset(CGPointMake(0, CGFloat.max), animated: true)
:
Boom, instantaneously, my tableView disappears.
tableView.setContentOffset(CGPointMake(0, self.tableView.contentSize.height - self.tableView.frame.size.height), animated: true)
:
Inaccurate. It doesn't get all the way to the bottom. Sometimes, it overshoots!
tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: self.replies.count - 1, inSection: 0), atScrollPosition: .Bottom, animated: true)
Again, like the previous one, this is inaccurate.
I know why this is inaccurate. What I need is a solution for this...
Here is a bit of code to run through:
class RepliesTableViewController: UITableViewController {
var cachedHeights = [Int: CGFloat]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
self.cachedHeights[indexPath.row] = cell.frame.size.height
}
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if let height = cachedHeights[indexPath.row] {
return height
} else {
return 113
}
}
}
Remember, only the initial scroll to the bottom doesn't go all the way . If I use my finger to scroll all the way to the bottom, then scroll up to the top and trigger a scroll to the bottom, it will be perfect.
The reason is simple: I will have triggered tableView.willDisplayCell
on every single cell, which means all the heights are already cached . This means tableView.estimatedHeightForRowAtIndexPath
works perfectly after the initial scroll.
However, if I never scroll to the bottom to cache all the heights and I try to programmatically scroll to the bottom, it won't get there. Why? Because I have the tableView.estimatedHeightForRowAtIndexPath
return 113.
Some people might argue that I need a more accurate estimate, but I refuse to entertain this thought. My cells can be as small as 50 and as large as 5000. There is no accurate estimate .
How do I mitigate this?
Perhaps I need to cache all my heights at a different time? What time is that? I don't want to do any calculations of my own. The beauty of tableView.willDisplayCell
is that I can cache cell.frame.size.height
instead of doing my own tedious calculations.
Edit 2: I have a hilarious solution... which is extremely clunky.. and unacceptable... but technically it works. Appended for amusement.
func scrollToBottom() {
self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: self.replies.count - 1, inSection: 0), atScrollPosition: .Bottom, animated: true)
}
override func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
if !atBottom {
self.tableView.setContentOffset(CGPointMake(0, tableView.contentOffset.y + 200), animated: true)
}
}
override func scrollViewDidScroll(scrollView: UIScrollView) {
atBottom = scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)
}
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 113.0; // set to whatever your "average" cell height is
This way your tableCell will reposition without the inaccuracy you mention
Update: ( Remove this function )
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if let height = cachedHeights[indexPath.row] {
return height
} else {
return 113
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.