macos - SwiftUI macOS onDrop 简单文本总是失败

尝试实现文本文件的简单拖放:

struct ContentView: View {
    
    @State private var drag = false
    
    var body: some View {
        Text("Hello, world!")
            .frame(width: 300, height: 300)
            .onDrop(of: [.url], isTargeted: $drag) { (providers, location) in
                
                
                print("Can load", providers.first?.canLoadObject(ofClass: NSURL.self) == true) // Always false
                
                providers.first?.loadItem(forTypeIdentifier: UTType.url.identifier, options: nil, completionHandler: { secureCoding, error in
                    
                    if let error = error {
                        print(error) // Cannot load representation of type ...
                    }
                    
                    if let item = secureCoding as? Data { // Always nil
                        print("got data")
                    }
                })
                
                return true
            }
    }
}

尝试使用已删除文件的 UTType (public.url,public.data) 和 loadItem(forTypeIdentifier)。我试过的都没有用。发现了类似的问题,但它们不起作用,答案看起来已经过时了。

我有旧的 Cocoa 代码,带有 registerForDraggedTypes,如果可行的话,这看起来要简单得多。

回答1

刚刚使用纯 .txt 文件进行了修改和测试。 Xcode 13.3 / macOS 12.3.1

@State private var text = "Drop Here"
    var body: some View {
        Text(text)
            .frame(width: 200, height: 200).border(.red)
            .onDrop(of: ["public.file-url"], isTargeted: $dragOver) { providers -> Bool in
                providers.first?.loadDataRepresentation(forTypeIdentifier: "public.file-url", completionHandler: { (data, error) in
                    if let data = data, let path = NSString(data: data, encoding: 4), let url = URL(string: path as String) {
                        if let value = try? String(contentsOf: url, encoding: .utf8) {
                            DispatchQueue.main.async {
                                 self.text = value
                            }
                        }
                    }
                })
                return true
            }

*注意:我不记得确切的位置,但我在 Apple 的文档中遇到过,我们必须为特定用例使用具体的 UTTypes 而不是通用的,即。 fileURL 确实是 URL,但为了匹配它必须准确指定!

回答2

我想发布我自己的答案,只是为了指出陷阱。感谢@Asperi,我得到了一个工作样本。

  1. .onDrop(of: [.fileURL],必须是 UTType.fileURL(或 public.file-url),而不是 UTType.url
  2. 我用的是 providers.first?.loadItem(forTypeIdentifier:...,需要是 loadDataRepresentation(forTypeIdentifier:...
  3. 读取数据:

    使用 let path = String(data: data, encoding: .utf8) 有效。下一步很重要,我需要使用 URL(string:)。不是 URL(fileURLWithPath:)

    使用 URL(fileURLWithPath:) 会产生看起来像 URL 的东西,具有安全范围。

其他小提示:

使用 let path = String(data: data, encoding: .utf8) 有效,不需要 NNString

使用 UTType.fileURL(和 UTType.fileURL.identifier 用于 String)也有效,不需要用于硬编码 "public.file-url"

相似文章

javascript - 拖放时交换元素

我在Wordpress中工作,我正在努力做到这一点,所以当一个可拖动的部分放在另一块的位置时,它们会交换位置,但是每次我放下一块时,什么都没有发生。下面是CSS部分,JS部分和htmlpart.Eac...