14

I have an XML file in my Xcode Project, and I'm trying to first save it to disk, and secondly how can I tell if I've successfully saved it? Is this the proper approach? Using the simulator I navigated to the new "Files" folder in iOS 11 and I don't see it but I'm not sure if it should be there or not?

guard let path = Bundle.main.url(forResource: "sample", withExtension: "xml") else {print("NO URL"); return}
    let sample = try? Data(contentsOf: path)


print("sample XML = \(String(describing: sample?.debugDescription))")

//put xml file on the device
let filename = getDocumentsDirectory().appendingPathComponent("sample.xml")
do {
    try sample?.write(to: filename)
} catch {
    print("ERROR")
}

updated to include my check if file exists:

 //check if file exists
    let checkPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
    let url = URL(fileURLWithPath: checkPath)
let filePath = url.appendingPathComponent("sample.xml").path
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath) {
    print("FILE AVAILABLE")
} else {
    print("FILE NOT AVAILABLE")
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
GarySabo
  • 5,806
  • 5
  • 49
  • 124
  • Naming your var path an url object is misleading. You can use FileManager method fileExists(atPath:) and pass yourURLObject.path to it – Leo Dabus Sep 27 '17 at 20:19
  • Thanks @LeoDabus it says the file exists but it's not listed in the file folder? Shouldn't it be there? – GarySabo Sep 27 '17 at 20:43
  • Which folder? The bundle is read only? – Leo Dabus Sep 27 '17 at 20:44
  • The app that iOS 11 added called "Files" – GarySabo Sep 27 '17 at 20:44
  • Not sure what you mean, can you elaborate? – GarySabo Sep 27 '17 at 20:46
  • ok, it still says it's available though? But how can I access it on device? Or is my code incorrectly telling me it's there? – GarySabo Sep 27 '17 at 21:00
  • I wanted to see the file itself in the Files App so that I could bring up the share action? – GarySabo Sep 27 '17 at 21:03
  • You can use UIDocumentInteractionController and let the user select where he wants to save your file when you share your url. The user needs to select save to files. – Leo Dabus Sep 27 '17 at 21:07
  • Resuming there is no need to write it to the Documents directory. You can export directly using your file url located at your bundle. – Leo Dabus Sep 27 '17 at 21:14
  • You will need also to pass the correct xml uti (type identifier) from your url which you can use this extension I answered here https://stackoverflow.com/questions/28570627/how-to-find-file-uti-for-file-withouth-pathextension-in-a-path-in-swift/34772517?s=1|6.7962#34772517 – Leo Dabus Sep 27 '17 at 21:17
  • @LeoDabus thank you I'll work with this and post an answer here with the code if I get working. – GarySabo Sep 27 '17 at 21:19
  • please have a look at https://stackoverflow.com/a/51764198/7276810 – Rashid KC Aug 09 '18 at 10:08

2 Answers2

25

You can use UIDocumentInteractionController and let the user select where he wants to save your file when you share your url. The user just needs to select save to files and choose which directory to save the file you are exporting.

You can use UIDocumentInteractionController to share any file type located inside your App bundle, at your Documents directory or another folder accessible from your App.

class ViewController: UIViewController {
    let documentInteractionController = UIDocumentInteractionController()
    func share(url: URL) {
        documentInteractionController.url = url
        documentInteractionController.uti = url.typeIdentifier ?? "public.data, public.content"
        documentInteractionController.name = url.localizedName ?? url.lastPathComponent
        documentInteractionController.presentOptionsMenu(from: view.frame, in: view, animated: true)
    }
    @IBAction func shareAction(_ sender: UIButton) {
        guard let url = URL(string: "https://www.ibm.com/support/knowledgecenter/SVU13_7.2.1/com.ibm.ismsaas.doc/reference/AssetsImportCompleteSample.csv?view=kc") else { return }
        URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data, error == nil else { return }
            let tmpURL = FileManager.default.temporaryDirectory
                .appendingPathComponent(response?.suggestedFilename ?? "fileName.csv")
            do {
                try data.write(to: tmpURL)
                DispatchQueue.main.async {
                    self.share(url: tmpURL)
                }
            } catch { 
                print(error)
            }

        }.resume()
    }
}

extension URL {
    var typeIdentifier: String? {
        return (try? resourceValues(forKeys: [.typeIdentifierKey]))?.typeIdentifier
    }
    var localizedName: String? {
        return (try? resourceValues(forKeys: [.localizedNameKey]))?.localizedName
    }
}

edit/update:

If you would like to expose the files located on your App Bundle's document directory you can check this post How can I display my App documents in the Files app for iPhone

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • 1
    The ```Add``` button in the Files view controller is not selectable, because there are no folders. So how do you save the file? – Supertecnoboff Mar 02 '18 at 22:56
  • 1
    @Supertecnoboff Sorry your question it is unclear. You need to select iCloud Drive. After that the add button should become available. Then you just need to select the folder where the file should be copied to. – Leo Dabus Mar 02 '18 at 22:58
  • 3
    Ah I see, thanks very much. Yeah I was trying to save the file by using the ```On my iPhone``` option which wasn't letting me select the ```Add``` button. Kind of annoying but oh well. – Supertecnoboff Mar 02 '18 at 23:03
  • @LeoDabus i have a feeling you might be able to help me understand my situation, any guidance would be appreciated: [https://stackoverflow.com/questions/67126367/how-to-play-a-video-from-url-using-skvideonode] – Ojay Apr 29 '21 at 13:10
  • Sharing a file using `UIActivityViewController` is another option to using `UIDocumentInteractionController`. It provides a "Save to Files" option along with many others. – HangarRash Nov 26 '22 at 04:46
6

Add these two keys to 'info.plist' -

...
<key>UIFileSharingEnabled</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
...

After this, files saved in '.documentDirectory' will appear in 'Files App' inside a folder with your app name.

If editing 'info.plist' in Xcode then add below keys -

Application supports iTunes file sharing = YES
Supports opening documents in place = YES

info.plist

ReflectCode
  • 111
  • 2
  • 4
  • This doesn’t add anything new to the post. It is already mentioned in the bottom of my answer [How can I display my App documents in the Files app for iPhone](https://stackoverflow.com/a/70613710/2303865) – Leo Dabus Feb 25 '23 at 16:00