简体   繁体   English

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

[英]Reading files from external storage in iOS 13

I have an iOS app that is trying to read files from an external storage device without importing them into the App's sandbox.我有一个 iOS 应用程序,它试图从外部存储设备读取文件而不将它们导入应用程序的沙箱。

I have followed Apple's documentations outlined here to do this --我已按照此处概述的 Apple 文档来执行此操作-

Providing Access to Directories 提供对目录的访问

I'm able to retrieve the selected directory ( which is on an external storage device connected via the Lightning port ) and enumerate the files inside the directory.我能够检索选定的目录(位于通过 Lightning 端口连接的外部存储设备上)并枚举目录中的文件。

However, when I try to do something with those files as per the recommended pattern, I get a failure and basically get permission errors on the file.但是,当我尝试按照推荐的模式对这些文件执行某些操作时,我遇到了失败,并且基本上会出现该文件的权限错误。

        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() }

I should add that this works JUST FINE if the files are on iCloud Drive via Simulator.我应该补充一点,如果文件通过模拟器在 iCloud Drive 上,这很好用。 It fails both on external devices and iCloud Drive on a real device.它在外部设备和真实设备上的 iCloud Drive 上都失败了。

Here is a full working project that demonstrates the failure.是一个完整的工作项目,演示了失败。

  1. Running on simulator accesses iCloud Drive files just fine.在模拟器上运行访问 iCloud Drive 文件就好了。 But running on device fails.但是在设备上运行失败。
  2. Running on device to access USB drive fails.在设备上运行以访问 USB 驱动器失败。

So, this seems like a documentation issue with the link posted above.因此,这似乎是上面发布的链接的文档问题。 When the user selects a folder, all files and folders are recursively granted access and automatically security scoped.当用户选择一个文件夹时,所有文件和文件夹都会被递归授予访问权限并自动设置安全范围。 The line guard file.startAccessingSecurityScopedResource() always returns false.线路guard file.startAccessingSecurityScopedResource()总是返回 false。

The trick to getting this work is NOT to try to security scope individual files, but to ensure that this code snippet does not run BEFORE you access files.获得这项工作的技巧不是尝试对单个文件进行安全范围,而是确保在您访问文件之前此代码片段不会运行。

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

As long as you continue to access files while the pickedFolderURL is inside security scope, you will be successful.只要在pickedFolderURL安全范围内时继续访问文件,您就会成功。

Hope this helps somebody.希望这可以帮助某人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM