How it works
DropSession represents a single in-progress drop as the user drags content over one of your views. SwiftUI hands you a session so you can inspect what's being carried, decide whether the current view can accept it, and coordinate the visual response before the drop completes. Reach for it whenever a view needs to react to a drag while it's still hovering — not just when the items finally land — so you can validate types, highlight a target, or refuse content that doesn't fit.
Declare a drop target with onDrop(of:isTargeted:)
A view becomes a drop destination when you attach a drop modifier; the session exists only within the lifetime of that target. Here the
RoundedRectangleis made droppable byonDrop(of: [.text], isTargeted: nil), which is the entry point that gives aDropSessionsomething to land on.Constrain the session by accepted content types
The
of:parameter lists the uniform type identifiers the session is allowed to carry, so SwiftUI can vet a drag before it ever reaches your code. Passing[.text]means thisDropSessiononly proceeds for plain-text payloads, and other content is rejected automatically.Track hover state with isTargeted
The
isTargeted:binding reflects, in real time, whether the active session is currently over this view — the moment-to-moment signal aDropSessionprovides. Passingnilopts out of that feedback here, but binding it to state is how you'd drive a highlight while the drag hovers.Receive the payload and complete the session
When the user releases, the closure runs with the session's item providers so you can pull out the dropped values. The
providers inclosure flipsdropped = trueto record the result, and itsreturn truetells theDropSessionthe drop was accepted rather than refused.
return true to return false and the DropSession will report the drop as rejected, so the closure's side effects stay but the system treats the content as not accepted.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 DropSessionDemo: View {
@State private var dropped = false
var body: some View {
VStack(spacing: 16) {
Text("Drag a string here")
.font(.headline)
RoundedRectangle(cornerRadius: 12)
.fill(dropped ? Color.green.opacity(0.3) : Color.gray.opacity(0.2))
.frame(height: 120)
.overlay(Text(dropped ? "Dropped!" : "Drop zone"))
.onDrop(of: [.text], isTargeted: nil) { providers in
dropped = true
return true
}
}
.padding()
}
}