編集: https://streamable.com/rfymはそれを実際に示します。Scroll To Bottom を初めて押したとき、最後までスクロールしません。次に、手動で一番下までスクロールし、すばやく上にスクロールします。Scroll To Bottom をもう一度押すと、cachedHeights を使用しているため、正しく機能します。
だから、私はこれについて多くの答えを見てきましたが、どれも私にはうまくいかないようで、他の多くの人にもうまくいかないと確信しています:
tableView.setContentOffset(CGPointMake(0, CGFloat.max), animated: true)
:
ブーム、瞬時に、私のtableViewが消えます。
tableView.setContentOffset(CGPointMake(0, self.tableView.contentSize.height - self.tableView.frame.size.height), animated: true)
:
不正確。底までは入りません。時々、それはオーバーシュートします!
tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: self.replies.count - 1, inSection: 0), atScrollPosition: .Bottom, animated: true)
繰り返しますが、前のものと同様に、これは不正確です。
これが不正確である理由はわかっています。私が必要としているのは、これに対する解決策です...
実行するコードは次のとおりです。
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
}
}
}
一番下までの最初のスクロールだけは最後まで行かないことに注意してください。指を使って一番下までスクロールしてから一番上までスクロールし、一番下までスクロールすると完璧です。
理由は簡単です。tableView.willDisplayCell
すべての単一セルでトリガーされます。これは、すべての高さが既にキャッシュされていることを意味します。これはtableView.estimatedHeightForRowAtIndexPath
、最初のスクロール後に完全に機能することを意味します。
ただし、すべての高さをキャッシュするために一番下までスクロールせず、プログラムで一番下までスクロールしようとすると、そこに到達しません。なんで?私はtableView.estimatedHeightForRowAtIndexPath
リターン113を持っているからです。
もっと正確な見積もりが必要だと主張する人もいるかもしれませんが、私はこの考えを楽しませることを拒否します. セルの数は、50 個から 5000 個まであります。正確な見積もりはありません。
これを軽減するにはどうすればよいですか?
おそらく、すべての高さを別の時間にキャッシュする必要がありますか? それは何時ですか?自分で計算したくない。の利点は、面倒な計算を自分で行う代わりにtableView.willDisplayCell
キャッシュできることです。cell.frame.size.height
編集2:私は陽気な解決策を持っています...これは非常に不格好です..そして受け入れられません...しかし、技術的には機能します。趣味で追加。
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)
}