UIDocumentPickerViewController - Open folder from 3rd party file provider

Hi,

I am trying to use UIDocumentPickerViewController to select a folder in a 3rd party file provider as a "default save location". The goal would be to have that folder be the automatic location to save to whenever the app needs to write a file out to disk, instead of the app's Documents directory.

When I present the UIDocumentPickerViewController for selecting folders, however, every 3rd party file provider is grayed out. Only "On this Device" and "iCloud Drive" are available.

let controller = UIDocumentPickerViewController(documentTypes: [kUTTypeFolder as String], in: .open)
controller.delegate = self
controller.allowsMultipleSelection = false

present(controller, animated: true, completion: nil)

The documentation states:

"With iOS 13, users can select a directory from any of the available file providers using a UIDocumentPickerViewController."

It seems strange that this is specifically called out in the docs, but it doesn't work at all. One hypothesis that I have is that there is some confusion in the system between kUTTypeFolder and kUTTypeDirectory which is causing this issue. But it's weird that this would be an issue from iOS 13 through iOS 15.

As a workaround, I also tried moving/copying a temporary directory with UIDocumentPickerViewController to the 3rd party provider, and using the resulting security-scoped URL to create new files. However, it seems that it doesn't grant proper permissions because whenever I try to create files in that folder, it throws an error claiming the file doesn't exist (duh, that's what I'm trying to do.)

let temporary = try! TemporaryFile(creatingTempDirectoryForFilename: "placeholder")
        FileManager.default.createFile(atPath: temporary.fileURL.path, contents: nil, attributes: nil)

let controller = UIDocumentPickerViewController(documentTypes: [kUTTypeFolder as String], in: .open)
controller.delegate = self
controller.allowsMultipleSelection = false

present(controller, animated: true, completion: nil)
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
    let folderURL = urls.first!

    let randomNumber = String(format: "%X", arc4random())
    guard folderURL.startAccessingSecurityScopedResource() else {
        Swift.debugPrint("Cannot access security-scoped URL: \(folderURL)")
        return
    }

    defer { folderURL.stopAccessingSecurityScopedResource() }

    let fileURL = folderURL.appendingPathComponent(randomNumber).appendingPathExtension("txt")

    var error: NSError?
    NSFileCoordinator().coordinate(writingItemAt: fileURL, options: .forReplacing, error: &error) { fileURL in
        let data = Data(randomNumber.utf8)
        do {
            try data.write(to: fileURL, options: [])
        } catch {
            print("error writing file:")
            print(error)
        }
    }
}
error writing file:
Error Domain=NSCocoaErrorDomain Code=4 "The file “3A7F4A2.txt” doesn’t exist." UserInfo={NSFilePath=/private/var/mobile/Containers/Shared/AppGroup/D9D4024B-AD43-4B57-920B-D8E2B5ED7645/File Provider Storage/non-file/d_LOCAL-0A6C7195-23D8-43AE-9CBC-B84F063E2B44/3A7F4A2.txt, NSUnderlyingError=0x2817ea100 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}

Does anyone have an idea for a workaround for this issue? Are there any known 3rd party file providers which are known to work? Is there any reason this would be disallowed? Finally, does anyone have an idea how I could implement the intended functionality in a way that I haven't thought of, yet?

Unfortunately, it is not possible to select any folder from 3rd party providers. I wanted to do the same and had grayed out file providers. I reported a bug 2 weeks ago and apple answered: "Works by design". I agree with you that the documentation says something else.

Also, when you select a file from the picker, the secure-scoped url only gives you permission to modify the file. You don't get any permissions to the folder which contains the file.

Our workaround is to export the file with UIActivityViewController. Then, you can open the file with the picker. Another solution involves creating your own UI and use the file providers own sdks.

I reported a bug 2 weeks ago

What was your bug number?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I would be very interested to hear more on this topic, too — I always assumed this is because most 3rd party providers deliberately chose not to integrate with the file provider APIs in full (due to security considerations, complexity or something else). This is based on the fact that some providers seem to work, e.g. Secure ShellFish app.

@navoshta Thank you so much for pointing out Secure ShellFish. I tried all the mainstream apps, such as Google Drive, Dropbox, Box, OneDrive, etc, as well as Termius, and none of them worked. However, for some reason Secure ShellFish DOES work. I wonder what makes them different. Is there an API or something that all of these apps have failed to implement? Part of me hoped it was just an iOS issue so that it could be fixed in one location. This is interesting...

@jadardev Choosing to not implement some of the Apple's file provider APIs is my guess, although I could be wrong. By the way, Secure ShellFish developer has a very helpful GitHub repo with code examples on how to integrate with file providers: https://github.com/palmin/open-in-place

My bug number is FB9703910.

Thanks.

Earlier you wrote:

I reported a bug 2 weeks ago and apple answered: "Works by design".

That was quite surprising so I wanted to check on the state of your bug. AFAICT it’s not been resolved and we’ve not sent you any indication that this is ‘working as designed’.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

UIDocumentPickerViewController - Open folder from 3rd party file provider
 
 
Q