🍎

[SwiftUI]スクロールのポジション検知

に公開1

成果物

ScrollViewでスクロール量次第で何かしら処理をしたい時に、
ポジション検知することで実現出来ます。
以下の成果物は一定のスクロールをしたらTopにViewを表示する機能です。
逆にその一定の位置以前にまた戻ればViewは消えるようになります。

ソース

https://github.com/chiii-arai/swiftui-examples/blob/main/swiftui-examples/Examples/DemoScrollViewOffsetView.swift

参考

https://stackoverflow.com/questions/62588015/get-the-current-scroll-position-of-a-swiftui-scrollview

Discussion

tana00tana00

GeometryReaderのクロージャ内でDispatchQueue.main.asyncを使用する理由は以下の通りです:

  1. レイアウトの更新サイクルの問題を防ぐため:
  • GeometryReaderは SwiftUI のレイアウトサイクル中に呼び出されます
  • この時点で直接 @State 変数(offset)を更新すると、レイアウトループが発生する可能性があります
  1. 状態更新の安全性を確保するため:
  • SwiftUIのビュー更新は必ずメインスレッドで行う必要があります
  • @Stateプロパティの更新も同様にメインスレッドで行う必要があります
  1. レイアウト処理との分離:
  • asyncを使用することで、位置情報の更新をレイアウト計算から分離できます
  • これにより、レイアウトの計算中に状態を変更することによる予期しない動作を防ぎます

このアプローチは、SwiftUIのビューの更新とGeometryReaderによる位置情報の取得を安全に行うためのベストプラクティスとして広く使用されています。