如何在 SwiftUI 中以异步方式使用 Transferable?

Yak*_*hzi 9 macos appkit ios swift swiftui

我想将应用程序中的文件(代表网络驱动器上的文件)拖到用户的桌面或 Finder 窗口。因此,只有在拖放操作结束后才应下载该文件。

使用 AppKit 我可以使用File Promises实现此行为。但对于 SwiftUI 来说,似乎没有等价的东西。唯一的选择是使用NSItemProvideror Transferable(或两者组合)(请参阅此问题)。但既不NSItemProvider也不Transferable支持这种异步行为。

主要问题是在拖动会话开始时调用itemProvider闭包FileRepresentation,从而也开始下载文件。这使得该功能无法使用,例如,如果您一次拖动一个大文件或多个文件。

struct Item: Identifiable, Transferable {
    let id = UUID()
    let name: String
    let description: String
    let url: URL

    static var transferRepresentation: some TransferRepresentation {
        FileRepresentation(contentType: .fileURL) { (item: DragItem) in
            let urlSession = URLSession(configuration: .default)
            // This download is already started when the drag & drop session starts
            let (tempURL, response) = try! await urlSession.download(from: item.url)
            return SentTransferredFile(tempURL)
        }
    }
}

let items = [
    Item(name: "Name 1", description: "Description 1", url: URL(string: "https://...")),
    Item(name: "Name 2", description: "Description 2", url: URL(string: "https://...")),
    Item(name: "Name 3", description: "Description 3", url: URL(string: "https://..."))
]

struct Test: View {
    var body: some View {
        Table {
            TableColumn("Column 1") { item in
                Text(item.name)
            }
            TableColumn("Column 2") { item in
                Text(item.description)
            }
        } rows: {
            ForEach(items) { item in
                TableRow(item)
                    .itemProvider {
                        let provider = NSItemProvider()
                        provider.register(item)
                        return provider
                    }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

NSFilePromiseProvider我怎样才能在 SwiftUI 中实现像 AppKit 中使用and一样的异步行为NSFilePromiseProviderDelegate