SwiftUI Drag & Drop
SwiftUI で Drag & Drop を表現するのに要件に合わせていくつかの選択肢が用意されている。
iOS 16 から Transferable protocol に適合することでアプリ間でのデータのやり取りができるようになる。この延長として、 Drag と Drop が可能な View として SwiftUI 上で表現できるようになっている。
iOS 16 からの draggable/dropDestination を利用することで簡単に Drag & Drop を実現可能
draggable で Drag 可能な View に
dropDestionation で Drop 可能な View に
isTargeted
で drop 対象になっていることが検知できる
Drag 時の preview をカスタマイズすることは可能
iOS 14 からは NSItemProvider に適合することで onDrag/onDrop で表現可能になる
onDrag で Drag 可能な View に
preview
が使えるのは iOS 15 から
onDrop で Drop 可能な View に
Drop 時のハンドリングは DropDelegate が用意されている
iOS 16 以上がターゲットでも Drop 時のハンドリングが必要な場合はこちらの選択肢が有力になる
iOS 13 からは DragGesture で表現可能
基本的に全てハンドリングできる
Drag & Drop の実装も書く必要があるのと、スクロールイベントが干渉すると実装が難しい
iOS | API | 実装 | ハンドリング |
---|---|---|---|
iOS 16 | draggable/dropDestination | 不要 | できない |
iOS 14 | onDrag/onDrop | 一部必要 | ドロップはできる |
iOS 13 | DragGesture | 全て+スクロールも | 全てできる |
LazyVGrid に付与した dropDestination はスクロールすると一度破棄されることがあるので、ドラッグしたままスクロールしてドロップしようとするとできないことがある。 iOS 17.5 ではドラッグした状態でスクロールして再表示した LazyVGrid に dropDestination が適用されていないような挙動を見せる。 iOS 18 では発生しない。また iOS 17.5 でも LazyVGrid に換えて VStack + HStack でレイアウトすれば再表示しても dropDestination が適用されていてドラッグ可能。