Open6

SwiftUI Drag & Drop

ykwsykws

SwiftUI で Drag & Drop を表現するのに要件に合わせていくつかの選択肢が用意されている。

https://developer.apple.com/documentation/swiftui/drag-and-drop

iOS 16 から Transferable protocol に適合することでアプリ間でのデータのやり取りができるようになる。この延長として、 Drag と Drop が可能な View として SwiftUI 上で表現できるようになっている。

https://developer.apple.com/documentation/CoreTransferable/Transferable

https://developer.apple.com/videos/play/wwdc2022/10062/

ykwsykws

iOS 16 からの draggable/dropDestination を利用することで簡単に Drag & Drop を実現可能

draggable で Drag 可能な View に

https://developer.apple.com/documentation/swiftui/view/draggable(_:)

dropDestionation で Drop 可能な View に

https://developer.apple.com/documentation/swiftui/view/dropdestination(for:action:istargeted:)

isTargeted で drop 対象になっていることが検知できる

Drag 時の preview をカスタマイズすることは可能

https://developer.apple.com/documentation/swiftui/view/draggable(_:preview:)

ykwsykws

iOS 14 からは NSItemProvider に適合することで onDrag/onDrop で表現可能になる

onDrag で Drag 可能な View に

https://developer.apple.com/documentation/swiftui/view/ondrag(_:)

preview が使えるのは iOS 15 から

https://developer.apple.com/documentation/swiftui/view/ondrag(_:preview:)

onDrop で Drop 可能な View に

https://developer.apple.com/documentation/swiftui/view/ondrop(of:istargeted:perform:)

Drop 時のハンドリングは DropDelegate が用意されている

https://developer.apple.com/documentation/swiftui/dropdelegate

iOS 16 以上がターゲットでも Drop 時のハンドリングが必要な場合はこちらの選択肢が有力になる

ykwsykws
iOS API 実装 ハンドリング
iOS 16 draggable/dropDestination 不要 できない
iOS 14 onDrag/onDrop 一部必要 ドロップはできる
iOS 13 DragGesture 全て+スクロールも 全てできる
ykwsykws

LazyVGrid に付与した dropDestination はスクロールすると一度破棄されることがあるので、ドラッグしたままスクロールしてドロップしようとするとできないことがある。 iOS 17.5 ではドラッグした状態でスクロールして再表示した LazyVGrid に dropDestination が適用されていないような挙動を見せる。 iOS 18 では発生しない。また iOS 17.5 でも LazyVGrid に換えて VStack + HStack でレイアウトすれば再表示しても dropDestination が適用されていてドラッグ可能。