9

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

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

提供对目录的访问

我能够检索所选目录(位于通过 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 上都失败。

是一个演示失败的完整工作项目。

  1. 在模拟器上运行可以很好地访问 iCloud Drive 文件。但在设备上运行失败。
  2. 在设备上运行以访问 USB 驱动器失败。
4

1 回答 1

11

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

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

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

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

希望这可以帮助某人。

于 2020-03-09T00:45:10.033 回答