我正在开发一款 SwiftUI 应用,希望支持拖放文件功能来处理任何文件。在尝试实现此功能时,我会尝试接受拖放到自定义拖放区域的任何文件并显示其 MIME 类型。我还提供了一个后备文件选择器 NSOpenPanel。此部分有效。
但是,处理任何文件时,拖放功能都会失败。
我的 HandleDrop 代码:
private func handleDrop(providers: [NSItemProvider]) -> Bool {
var success = false
for provider in providers {
print("Checking provider: \(provider)")
// Handle public.file-url
if provider.hasItemConformingToTypeIdentifier("public.file-url") {
print("Provider conforms to public.file-url")
provider.loadItem(forTypeIdentifier: "public.file-url", options: nil) { item, error in
if let url = item as? URL {
print("Dropped file URL: \(url)")
DispatchQueue.main.async {
droppedFileType = "MIME Type: \(url.mimeType ?? "Unknown")"
}
success = true
} else {
print("Failed to cast item to URL for public.file-url")
}
}
}
// Handle public.data
else if provider.hasItemConformingToTypeIdentifier("public.data") {
print("Provider conforms to public.data")
provider.loadItem(forTypeIdentifier: "public.data", options: nil) { item, error in
if let data = item as? Data {
let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString).appendingPathExtension("pdf")
do {
try data.write(to: tempURL)
print("Saved file to temporary URL: \(tempURL)")
DispatchQueue.main.async {
droppedFileType = "MIME Type: \(tempURL.mimeType ?? "Unknown")"
}
success = true
} catch {
print("Failed to write data to temporary file")
}
} else {
print("Failed to decode item as public.data")
}
}
}
// Unsupported type
else {
print("Provider does NOT conform to public.file-url or public.data")
}
}
return success
}
如上所述,文件选择器/NSOpenPanel 完美适用于所有文件类型。MIME 类型被正确检测并显示。但是,拖放提供程序虽然符合 public.data,但解码为数据失败。我的日志显示无法将项目解码为 public.data。我尝试使用 .png 或 .txt 等文件类型,但都失败了。
我的 .entitlement:
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.files.downloads.read-write</key>
<true/>
通过一些简单的调试,您可以看到 的类型
item
实际上是NSURL?
,即使在"public.data"
分支中也是如此。这是因为
loadItem(forTypeIdentifier:)
它在 Swift 中有点损坏。既然你无论如何都需要a
URL
,你就不再需要写入临时文件了。只需强制转换item
为URL
,它基本上与分支相同"public.file-url"
。还可以考虑使用
loadFileRepresentation
,它直接为您提供URL
。或者,像这样使用Transferable
-based修饰符:dropDestination
您修改和返回的方式
success
没有多大意义,并且不是并发安全的。您应该在完成处理程序之外success
将其设置为 true 。请记住,完成处理程序可以与 中的代码在不同线程上同时执行。handleDrop