从 iOS 13 中的外部存储读取文件

Reading files from external storage in iOS 13

我有一个 iOS 应用程序正在尝试从外部存储设备读取文件而不将它们导入应用程序的沙箱。

我已按照此处概述的 Apple 文档来执行此操作 --

Providing Access to Directories

我能够检索所选目录(位于通过 Lightning 端口连接的外部存储设备上)并枚举目录中的文件。

但是,当我尝试按照推荐的模式对这些文件执行某些操作时,我遇到了失败,基本上是文件权限错误。

        let shouldStopAccessing = pickedFolderURL.startAccessingSecurityScopedResource()
        defer {
          if shouldStopAccessing {
            pickedFolderURL.stopAccessingSecurityScopedResource()
          }
       }
       var coordinatedError:NSError?
       NSFileCoordinator().coordinate(readingItemAt: pickedFolderURL, error: &coordinatedError) { (folderURL) in
        let keys : [URLResourceKey] = [.isDirectoryKey]
        let fileList = FileManager.default.enumerator(at: pickedFolderURL, includingPropertiesForKeys: keys)!
        for case let file as URL in fileList {
            if !file.hasDirectoryPath {
                do {
                    // Start accessing a security-scoped resource.
                    guard file.startAccessingSecurityScopedResource() else {
                        // Handle the failure here.
                        //THIS ALWAYS FAILS!!
                        return
                    }

                    // Make sure you release the security-scoped resource when you are done.
                    defer { file.stopAccessingSecurityScopedResource() }

我应该补充一点,如果文件通过模拟器位于 iCloud Drive 上,则此方法工作正常。它在外部设备和真实设备上的 iCloud Drive 上都失败了。

Here 是一个完整的工作项目,展示了失败。

  1. 运行 在模拟器上可以正常访问 iCloud Drive 文件。但是设备上的 运行 失败。
  2. 运行 在设备上访问 USB 驱动器失败。

因此,这似乎是上面发布的 link 的文档问题。当用户选择一个文件夹时,所有文件和文件夹都被递归授予访问权限并自动设置安全范围。 guard file.startAccessingSecurityScopedResource() 行总是 returns 错误。

完成这项工作的诀窍不是尝试对单个文件进行安全范围处理,而是确保此代码片段不会 运行 在您访问文件之前。

   defer {
      if shouldStopAccessing {
        pickedFolderURL.stopAccessingSecurityScopedResource()
      }
   }

只要您在 pickedFolderURL 处于安全范围内时继续访问文件,您就成功了。

希望这对某人有所帮助。