How it works
ItemProviderTableRowModifier is the table-row modifier SwiftUI produces when you attach an item provider to a row inside a Table. It carries the NSItemProvider that describes a row's draggable payload, so the system knows what data to vend when that row is dragged out of the table and dropped into another view, app, or the wider system. Reach for it through the itemProvider(_:) modifier whenever you build a Table from explicit rows and want those rows to participate in drag-and-drop without hand-rolling your own gesture or drop-destination plumbing.
Build a Table that exposes its rows
ItemProviderTableRowModifier only applies to TableRow values, so the row content has to be written out explicitly rather than generated from a collection. The trailing rows: closure does exactly that, building each row by hand with
Table(songs) { ... } rows: { ... }so there is a concreteTableRowto modify.Produce one TableRow per element
Inside the rows builder, iterate your data and emit a row for each item; the modifier attaches to whatever individual row you return. Here
ForEach(songs) { song in TableRow(song) }yields a distinctTableRowbound to eachSong, giving you a per-row hook for the drag payload.Attach the payload with itemProvider(_:)
Calling
.itemProvider { ... }on a TableRow is what creates the ItemProviderTableRowModifier and wraps the row in it. The closure is asked for an NSItemProvider on demand, so it runs when a drag begins; in the example.itemProvider { NSItemProvider(object: song.title as NSString) }registers each row's title as its draggable representation.Describe the data through NSItemProvider
The NSItemProvider you return is the contract for the dragged content: it names the types and supplies the bytes the destination will receive. Bridging a value with
song.title as NSStringregisters a plain-text representation, so dropping the row elsewhere delivers the song's title string.Let the modifier compose with the row
ItemProviderTableRowModifier conforms to TableRowModifier and returns a modified row, so it slots into a row's chain just like a view modifier does on a view. Because
TableRow(song).itemProvider { ... }simply returns another row value, the table treats the result as the row to display and drag, with the surrounding.padding()left to the Table itself.
NSItemProvider(object: song.artist as NSString) and watch a dragged row now carry the artist instead of the title, confirming that the modifier vends exactly what its item provider describes.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 ItemProviderTableRowModifierDemo: View {
struct Song: Identifiable {
let id = UUID()
let title: String
let artist: String
}
let songs = [
Song(title: "Blue Skies", artist: "Ella"),
Song(title: "Take Five", artist: "Brubeck")
]
var body: some View {
Table(songs) {
TableColumn("Title", value: \.title)
TableColumn("Artist", value: \.artist)
} rows: {
ForEach(songs) { song in
TableRow(song)
.itemProvider { NSItemProvider(object: song.title as NSString) }
}
}
.padding()
}
}