Home > Enterprise >  Move file from app to phone documents folder
Move file from app to phone documents folder

Time:09-30

So in my app I have created a Test.JSON file that I want the user to be able to move to the documents directory, outside of the app. I understand I have to do this by using UIDocumentPickerViewController, but haven't found any way to proceed. I have created the Test.JSON file, and can use it from variable data.

I have this following code to open the UIDocumentPickerViewController:

let documentPicker =
UIDocumentPickerViewController(forExporting: [.documentsDirectory])
        
documentPicker.delegate = self

// Set the initial directory.
documentPicker.directoryURL = .documentsDirectory

// Present the document picker.
present(documentPicker, animated: true, completion: nil)

How can I attach the data file to the UIDocumentPickerViewController, so I can place it in the documents directory?

CodePudding user response:

Have you followed the instructions that Apple provides here? I'm summarizing the important bits here:

After the user taps Done, the system calls your delegate’s documentPicker(_:didPickDocumentsAt:) method, passing an array of security-scoped URLs for the user’s selected directories .... When the user selects a directory in the document picker, the system gives your app permission to access that directory and all of its contents.

So first, you need to implement the delegate methods so that you know what the user selects. Specifically, documentPicker(_:didPickDocumentsAt:) is the important one, although you'll want to listen for "cancel" as well. Then you need to access that scoped resource and write to it.

Here is an example that I took from the documentation linked above. This example only reads from the directory, but you can also write to it in the same way.

func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
    // Start accessing a security-scoped resource.
    guard url.startAccessingSecurityScopedResource() else {
        // Handle the failure here.
        return
    }

    // Make sure you release the security-scoped resource when you finish.
    defer { url.stopAccessingSecurityScopedResource() }

    // Use file coordination for reading and writing any of the URL’s content.
    var error: NSError? = nil
    NSFileCoordinator().coordinate(readingItemAt: url, error: &error) { (url) in
            
        let keys : [URLResourceKey] = [.nameKey, .isDirectoryKey]
            
        // Get an enumerator for the directory's content.
        guard let fileList =
            FileManager.default.enumerator(at: url, includingPropertiesForKeys: keys) else {
            Swift.debugPrint("*** Unable to access the contents of \(url.path) ***\n")
            return
        }
            
        for case let file as URL in fileList {
            // Start accessing the content's security-scoped URL.
            guard url.startAccessingSecurityScopedResource() else {
                // Handle the failure here.
                continue
            }

            // Do something with the file here.
            Swift.debugPrint("chosen file: \(file.lastPathComponent)")
                
            // Make sure you release the security-scoped resource when you finish.
            url.stopAccessingSecurityScopedResource()
        }
    }
}

CodePudding user response:

If you already have the URL for the document replace 'newFile' with the document URL. 'vc' is the current ViewController

Note asCopy = false will move the the document, asCopy = true will copy the document. There appears to be bug in iOS 16 which disables the Move button when asCopy = false.

//Present Document Picker
let controller = UIDocumentPickerViewController(forExporting: [newFile], asCopy: false)
vc.present(controller, animated: true) {
    //this will be called as soon as the picker is launched NOT after save
}
  • Related