使用文档选择器从 iCloud 中选择一个文件夹

Picking a Folder from iCloud with Document Picker

我正在尝试使用 Alamofire 使用文档选取器从 iCloud 导入文件夹以将其上传到服务器。我可以从 iCloud 导入单个文件,例如 .txt .pdf 文件,但我无法选择其中包含一些文件的文件夹。尝试 select 文件夹后出现以下错误:

Unable to load data: Error Domain=NSCocoaErrorDomain Code=257 "The file “xxxx” couldn’t be opened because you don’t have permission to view it." ... {Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied"}}

这是我的代码:

someFunctionToGetPickedFilePath = { (filePath) in
        let urlString = filePath.path
        let fileWithPath: URL = URL.init(fileURLWithPath: urlString)

        do {
            let fileData = try Data(contentsOf: fileWithPath)
            // upload the fileData to server with Alamofire upload request
        } catch {
            print("Unable to load data: \(error)")
        }
    }

"filePath" URL 这里的文档选择器函数是这样的:

func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
    // some code 
}

我已经尝试了将近 2 天的时间来寻找解决方案,但我似乎找不到解决方案。我如何从 iCloud 中选择一个文件夹,为什么我会收到此权限被拒绝的错误?任何回复将不胜感激。

请记住,当涉及到 iCloud 时,您处于沙盒中,因此您需要使用 FileManager 来获取适当的文件。

例如

  1. 确保在项目
  2. 中勾选了"iCloud Documents"
  3. 指定容器,例如您在 developer.apple.com 上指定的容器。 Xcode 会自动为您执行此操作,并显示为 iCloud.com.yourapp.identifier.whatever.abb
  4. 确保为您的应用程序启用了 iCloud,同样,如果您在其中正确设置了开发者 ID,Xcode 会为您执行此操作(Xcode -> Peferences - > 帐户(选项卡)...将其添加到此处..

现在,借助一些代码魔法,您可以实现这一点。虽然这有点复杂,但它是正确的方法(恕我直言,有点太正确了):

https://theswiftdev.com/2018/05/17/how-to-use-icloud-drive-documents/

但是你需要依赖FileManager(旧的NSFileManager)

您收到此错误是因为您正在获取文件所在文件夹的路径,就像@ivan-ičin 在评论中所说的那样,您无法根据文档从 iCloud 中选择整个文件夹。

因此,如果您尝试将特定文件夹的所有文件上传到您的服务器,我建议您获取该文件夹的 URL,然后使用以下代码您可以获得所有文件的列表存在于该文件夹中。

您可以通过以下方式获取您要选择的文档文件夹中所有文件的列表。

let fileManager = FileManager.default
let documentsURL = "YOUR FOLDER URL"
//If all files are in your app document directory then use this line
//fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]

do {
    let fileURLs = try fileManager.contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil)
    // Append files to an array here and then iterate the array later and upload files to server one by one.
} catch {
    print("Error while enumerating files \(documentsURL.path): \(error.localizedDescription)")
} 

获得 URL 后,您可以将它们附加到数组并使用 Alamofire 将它们一一上传到您的服务器。