Home > Enterprise >  How to use Transferable for Table Rows in SwiftUI
How to use Transferable for Table Rows in SwiftUI

Time:11-18

With WWDC 2022, Apple introduced the Transferable protocol to support Drag & Drop operations in an easy way. How can I use this new technique (in combination with the new draggable and dropDestination modifiers) for SwiftUI tables (not lists)?

The TableRowContent does not support the draggable and dropDestination modifiers. Also, when applying the modifiers directly to the views in the TableColumns, the drag / drop operation will only work on for that specific cell, and not the entire row. When adding the modifiers to all cells, it still does not work when dragging e.g. in an empty space inside of a row.

struct Item: Identifiable, Codable, Transferable {
    let id = UUID()
    let text: String

    static var transferRepresentation: some TransferRepresentation {
        CodableRepresentation(contentType: .text)
    }
}

struct Test: View {
    var body: some View {
        Table {
            TableColumn("Column 1") { item in
                Text(item.text)
                    .draggable(item) // This does only work when dragging not in the space between two columns
            }
            TableColumn("Column 2") { item in
                Text(item.text)
                    .draggable(item) // This does only work when dragging not in the space between two columns
            }
        } rows: {
            ForEach([Item(text: "Hello"), Item(text: "World")]) { item in
                TableRow(item)
                    .draggable(item) // This causes a compile-time error
                    .itemProvider { ... } // This does not work with Transferable and thus support my use case
            }
        }
    }
}

I want a similar behavior as the itemProvider modifier and the recently added contextMenu modifier on the TableRowContent , which allow the respective operation on the whole table row. I cannot use itemProvider, since it requires to return an NSItemProvider, which does not support my use case of dragging a file from a network drive to the Mac hard drive.

CodePudding user response:

I found out that you can register a Transferable object in the NSItemProvider:

TableRow(item)
    .itemProvider {
        let provider = NSItemProvider()
        provider.register(item)
        return provider
    }

Unfortunately the itemProvider closure is already called when the dragging session starts instead of when the drop was performed. But I guess this problem is a different question to answer.

  • Related