Estoy tratando de descargar un archivo usando AlamoFire y guardarlo en un directorio de descargas elegido por el usuario (como safari). Sin embargo, cada vez que configuro el directorio de descarga en una carpeta fuera de los documentos de mi aplicación, aparece el siguiente error (en un dispositivo iOS real):
downloadFileMoveFailed(error: Error Domain=NSCocoaErrorDomain Code=513 ""CFNetworkDownload_dlIcno.tmp" no se pudo mover porque no tiene permiso para acceder a "Descargas"." UserInfo={NSSourceFilePathErrorKey=/private/var/mobile/Containers/ Datos/Aplicación/A24D885A-1306-4CE4-9B15-952AF92B7E6C/tmp/CFNetworkDownload_dlIcno.tmp, NSUserStringVariant=(Mover), NSDestinationFilePath=/private/var/mobile/Containers/Shared/AppGroup/E6303CBC-62A3-4206-7C044-E934DEC /Almacenamiento del proveedor de archivos/Descargas/100MB.bin, NSFilePath=/private/var/mobile/Containers/Data/Application/A24D885A-1306-4CE4-9B15-952AF92B7E6C/tmp/CFNetworkDownload_dlIcno.tmp, NSUnderlyingError=0x281d045d0 {Error Domain=NSPOS Código=1 "Operación no permitida"}}, origen: archivo:///private/var/mobile/Containers/Data/Application/A24D885A-1306-4CE4-9B15-952AF92B7E6C/tmp/CFNetworkDownload_dlIcno.tmp, destino: archivo: ///private/var/mobile/Containers/Shared/AppGroup/E6303CBC-62A3-4206-9C84-E37041894DEC/File%20Provider%20Sto rabia/Descargas/100MB.bin)
El resumen de ese error es que no tengo permiso para acceder a la carpeta a la que acabo de otorgar acceso.
Aquí está mi código adjunto:
import SwiftUI import UniformTypeIdentifiers import Alamofire struct ContentView: View { @AppStorage("downloadsDirectory") var downloadsDirectory = "" @State private var showFileImporter = false var body: some View { VStack { Button("Set downloads directory") { showFileImporter.toggle() } Button("Save to downloads directory") { Task { do { let destination: DownloadRequest.Destination = { _, response in let documentsURL = URL(string: downloadsDirectory)! let suggestedName = response.suggestedFilename ?? "unknown" let fileURL = documentsURL.appendingPathComponent(suggestedName) return (fileURL, [.removePreviousFile, .createIntermediateDirectories]) } let _ = try await AF.download(URL(string: "https://i.imgur.com/zaVQDFJ.png")!, to: destination).serializingDownloadedFileURL().value } catch { print("Downloading error!: \(error)") } } } } .fileImporter(isPresented: $showFileImporter, allowedContentTypes: [UTType.folder]) { result in switch result { case .success(let url): downloadsDirectory = url.absoluteString case .failure(let error): print("Download picker error: \(error)") } } } }Para reproducir (ejecutar en un dispositivo iOS REAL!):
Set downloads directory en On my iPhoneSave to downloads directory Luego de una mayor investigación, descubrí que Safari usa el permiso de privacidad Files and Folders (ubicado en Settings > Privacy > Files and folders en un iPhone) para acceder a carpetas fuera del entorno limitado de la aplicación ( este enlace para la imagen de lo que estoy hablando) . Busqué en la web tanto como pude y no pude encontrar ninguna documentación para este permiso exacto.
He visto aplicaciones que no son de Apple (como VLC) que usan este permiso, pero no puedo entender cómo se otorga.
Intenté habilitar las siguientes propiedades de plist, pero ninguna funciona (porque luego me di cuenta de que son solo para macOS)
<key>NSDocumentsFolderUsageDescription</key> <string>App wants to access your documents folder</string> <key>NSDownloadsFolderUsageDescription</key> <string>App wants to access your downloads folder</string> <key>LSSupportsOpeningDocumentsInPlace</key> <true/> <key>UIFileSharingEnabled</key> <true/>¿Puede alguien ayudarme a descubrir cómo otorgar permisos a los archivos y carpetas y explicar qué hace? Apreciaría mucho la ayuda.