Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

I have followed Apple's documentations outlined here to do this --

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.

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. It fails both on external devices and iCloud Drive on a real device.

Here is a full working project that demonstrates the failure.

  1. Running on simulator accesses iCloud Drive files just fine. But running on device fails.
  2. Running on device to access USB drive fails.
like image 613
Kal Avatar asked Mar 03 '20 00:03

Kal


People also ask

Does iOS 13 support external storage?

Apple made this possible with the release of iOS 13 in 2019, adding native support for external storage devices using both Lightning and USB-C connectors.

Can iPhone read external hard drive?

You can use the Files app and other supported apps to access files stored on external devices, such as USB drives and SD cards, connected to your iPhone.


1 Answers

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.

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.

Hope this helps somebody.

like image 196
Kal Avatar answered Oct 22 '22 07:10

Kal