Estou trabalhando em um aplicativo no SwiftUI, no qual quero dar suporte à funcionalidade de soltar arquivo para manipular quaisquer arquivos. Enquanto tento implementar isso, estou tentando aceitar quaisquer arquivos soltos em uma área de soltar personalizada e exibir seu tipo MIME. Também forneço um seletor de arquivo de fallback NSOpenPanel. Esta parte funciona.
Entretanto, a funcionalidade de soltar falha ao manipular qualquer arquivo.
Meu código 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
}
Conforme mencionado acima, o File Chooser/NSOpenPanel funciona perfeitamente para todos os tipos de arquivo. O tipo MIME é detectado corretamente e exibido. No entanto, o provedor Drag & Drop, embora esteja em conformidade com public.data, a decodificação como Data falha. Meus Logs mostram que falhou ao decodificar o item como public.data. Tentei com tipos de arquivo como .png ou .txt, mas todos falharam.
Meu .direito:
<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/>
Com alguma depuração simples, você pode ver que o tipo de
item
é realmenteNSURL?
, mesmo na"public.data"
ramificação.Isso ocorre porque
loadItem(forTypeIdentifier:)
ele está meio quebrado no Swift .Já que você quer um
URL
de qualquer forma, não precisa mais escrever em um arquivo temporário. Basta fazer castitem
paraURL
e é basicamente o mesmo que o"public.file-url"
branch.Considere também usar
loadFileRepresentation
, que lhe dá diretamente umURL
. Ou use o modificadorTransferable
baseadodropDestination
em - assim:A maneira como você está modificando e retornando
success
não faz muito sentido e não é seguro para concorrência. Você deve definirsuccess
como true fora dos manipuladores de conclusão. Tenha em mente que os manipuladores de conclusão podem ser executados simultaneamente com o código emhandleDrop
, em um thread diferente.