WEBサイト制作・アプリ開発・システム開発・ブランディングデザイン制作に関するご相談はお気軽にご連絡ください。
構想段階からじっくりとヒアリングし、お客様の課題にあわせたアプローチ手法でお客様の“欲しかった”をカタチにしてご提案いたします。
Blog スタッフブログ
iOS
Swift
システム開発
[Swift]複数のUITableViewのスクロールを同期させる

こんにちは、株式会社MIXシステム開発担当のBloomです。
今回は複数のUITableViewやUIScrollViewでスクロールを同期させたい場合について、お仕事の中で得た知見を共有させていただきます。
UIScrollViewDelegate
extension ViewController: UITableViewDataSource, UITableViewDelegate, UIScrollViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 0
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
syncronizeScroll(scrollView: scrollView)
}
private func syncronizeScroll(scrollView: UIScrollView) {
guard !isSyncing else { return }
isSyncing = true
alignOffsets(scrollView)
isSyncing = false
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
alignOffsets(scrollView)
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if !decelerate { alignOffsets(scrollView) }
}
private func alignOffsets(_ scrollView: UIScrollView) {
let y = scrollView.contentOffset.y
self.tableView1.contentOffset.y = y
self.tableView2.contentOffset.y = y
}
}
syncronizeScroll関数内において、ここでは再帰的な呼び出しを防止するためにisSyncing変数を別途設置することで処理のループを防いでいます。
また、この関数内でsetContentOffset(_:animated:)を利用してしまうと慣性が消失してしまい使用感が悪化するため注意しましょう。
scrollViewDidEndDeceleratingにおいて慣性スクロールの終了時にまたスクロール位置の同期を行なっています。これはheightForRowAtやestimatedHeightForRowAtにおいての明示的な指定と関連しており、稀にスクロール位置がズレて同期されてしまうことへの対策になります。
これだけでふたつのUITableViewのスクロール位置を同期することができます。良かったですね。