How it works
A DragSession is the value SwiftUI hands you to describe a single drag operation while it is underway — the gesture that begins when a person picks up content and continues until they drop it or cancel. Rather than tracking pointer events yourself, you read a DragSession to learn what is being carried, where the drag currently is, and how its lifecycle is progressing. Reach for it when a plain draggable/dropDestination pair isn't enough and you need to coordinate behavior over the lifetime of the drag, such as customizing the preview, animating the source, or responding as the drag moves across your interface.
Start a drag with draggable(_:)
A
DragSessiononly exists once a draggable view is lifted, so the session begins at the source. Here.draggable("Apple")marks theText("🍎 Apple")view as a drag source and supplies theStringpayload that the session will carry. The transferable payload you provide is exactly what the session vends to any destination during the drag.Receive the payload at a dropDestination(for:)
A
DragSessionis resolved at a drop target, where SwiftUI delivers the items the session was carrying. The.dropDestination(for: String.self)modifier on theText(dropped)view accepts drags whose payload decodes toString, handing your closure theitemsarray; the example takesitems.firstand assigns it into thedroppedstate. The session's matched type (String.self) is what lets the destination opt in to this particular drag.Read the in-progress state during the drag
While the gesture is active, a
DragSessioncarries the live state of the operation — the dragged items, the current location, and the phase of the drag. You inspect these members from the API surfaces that vend a session (such as a drop destination's location-aware callbacks) to drive feedback as the user moves over a target like the.blue.opacity(0.15)drop zone, before the payload is committed in the closure that setsdropped.Drive UI from the session's outcome
Because the session ends with either a completed drop or a cancellation, you tie your view's reaction to that conclusion. The drop closure returns
trueto signal a successful drop and mutates@State private var dropped, so SwiftUI re-renders the destinationTextwith the carried value once the session completes.
.draggable("Apple") to .draggable("Banana") and run the demo — dragging onto the blue zone now sets dropped to "Banana", confirming that the session carries the exact payload you hand the source.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct DragSessionDemo: View {
@State private var dropped = "Drop here"
var body: some View {
VStack(spacing: 20) {
Text("🍎 Apple")
.font(.title2)
.padding()
.background(.yellow.opacity(0.3), in: RoundedRectangle(cornerRadius: 12))
.draggable("Apple")
Text(dropped)
.font(.headline)
.frame(maxWidth: .infinity, minHeight: 80)
.background(.blue.opacity(0.15), in: RoundedRectangle(cornerRadius: 12))
.dropDestination(for: String.self) { items, _ in
dropped = items.first ?? ""
return true
}
}
.padding()
}
}