TechnologiesSwiftUI

ItemProviderTableRowModifier struct

iOSmacOStvOSwatchOSvisionOS✓ renders

A table row modifier that associates an item provider with some base

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.

  1. 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 concrete TableRow to modify.

  2. 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 distinct TableRow bound to each Song, giving you a per-row hook for the drag payload.

  3. 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.

  4. 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 NSString registers a plain-text representation, so dropping the row elsewhere delivers the song's title string.

  5. 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.

Try it — Change the closure to 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.

ItemProviderTableRowModifier.swift
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()
    }
}
Live preview
Title Artist Blue Skies Ella Take Five Brubeck
Title Artist Blue Skies Ella Take Five Brubeck
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →