BLACK FRIDAY SALE: Save big on all my Swift books and bundles! >>

Trying to figure out how to export or e-mail or get a file some other way from one of my apps

Forums > SwiftUI

I'm at the point where I've figured out how to save files on the phone similar to what Paul had shown us with UserDefaults, using the code below. I'm now trying to figure out how I can access this file from somewhere else; attached to an e-mail, saved to the iCloud Drive, or whatever. Basically, I want a copy of the file verses.json on my laptop. The closest thing I've found is this:

https://www.hackingwithswift.com/quick-start/swiftui/how-to-export-files-using-fileexporter

but it doesn't have all the information I need and the one before and after it don't seem to help either. Does Paul have any tutorials on doing this? Or are there any videos on working with files in general?

extension FileManager {
    func getDocumentsDirectory() -> URL {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return paths[0]
    }
}

class Verses: ObservableObject {
    @Published var items = [VerseItem]() {
        didSet {
            if let encoded = try? JSONEncoder().encode(items) {
                let url = FileManager.default.getDocumentsDirectory().appendingPathComponent("verses.json")
                do {
                    try encoded.write(to: url)
                } catch {
                    print(error.localizedDescription)
                }
            }
        }
    }
    init() {
        let url = FileManager.default.getDocumentsDirectory().appendingPathComponent("verses.json")
        if let savedItems = try? Data(contentsOf: url) {
            if let decodedItems = try? JSONDecoder().decode([VerseItem].self, from: savedItems) {
                items = decodedItems
                return
            }
        }
        items = []
    }
}

   

I have upgraded my code above to the following below and it all seems to work, but I'm no closer to figuring out how to export files.

extension FileManager {
    func getDocumentsDirectory() -> URL {
        let paths = Self.default.urls(for: .documentDirectory, in: .userDomainMask)
        return paths[0]
    }
    func encode<T: Codable>(_ file: String, data: T) {
        if let encoded = try? JSONEncoder().encode(data) {
            let url = Self.default.getDocumentsDirectory().appendingPathComponent(file)
            do {
                try encoded.write(to: url)
            } catch {
                print(error.localizedDescription)
            }
        }
    }
    func decode<T: Codable>(_ file: String) -> T? {
        let url = Self.default.getDocumentsDirectory().appendingPathComponent(file)
        if let savedItems = try? Data(contentsOf: url) {
            if let decodedItems = try? JSONDecoder().decode(T.self, from: savedItems) {
                return decodedItems
            }
        }
        return nil
    }
}

class Verses: ObservableObject {
    @Published var items = [VerseItem]() {
        didSet {
            FileManager.default.encode("verses.json", data: items)
        }
    }
    init() {
        items = FileManager.default.decode("verses.json") ?? []
    }
}

   

While I haven't figured out how to export one of my saved files in my App from my phone, I did manage program a button to dump all my data into a string and then export it as a plain text CSV file into my iCloud Drive, using the information from these two urls:

https://www.hackingwithswift.com/quick-start/swiftui/how-to-export-files-using-fileexporter https://betterprogramming.pub/importing-and-exporting-files-in-swiftui-719086ec712

I still have a long ways to go in understanding this stuff, so if someone could point me to some more basic tutorials, I would appreciate it.

   

Hello, what is your use case for getting these files? Do you want the users of your app be able to access them also and possibly share them for debug purposes?

For your own apps, you can actually inspect all the data via Xcode. Like this:

Window -> Devices and Simulators -> select the device and app in the list -> click the small "gear" icon below -> Download container...

This will download special package, you can right-click the file on your Mac and select "Show package contents". It will show you everything in your apps directory.

Another option which I used recently is to make your app's "Documents folder" (usually the default one when you use FileManager) publicly available with the Files.app. This is matter of adding two keys to Info.plist file. I wrote a short blog post about it - https://nemecek.be/blog/57/making-files-from-your-app-available-in-the-ios-files-app

   

Yes, I want users to be able to access the data, even though I am currently the only user. I want to make it possible to get a copy of the data without having to use Xcode. The reasons for accessing the files are 1. To have a backup copy of the data for backup and restore purposes, 2. To have a copy of the data for doing other things with it, for instance, I have several apps that I use that at the end of the year I want to be able to get a copy of the data for tax purposes. I want a permanent copy of it in my tax records and for use in preparing my taxes.

I looked through your blog and that looks like a reasonable option. I'll have to play around with it. I don't want users, including myself, to have direct access to the data, because that could cause all kinds of issues. Instead I want them to access a copy of it. From reading your blog, it sounds like that is possible.

Thanks.

   

Nice! With the documents folder approach in files, you can use it as export destination while keeping your data either in a database or perhaps in the "Application Support" directory (the linked blog post shows how).

I think this will be pretty solid solution. Another option might be to export to iCloud Drive folder which gives the benefit of automatic backup (it works basically the same as documents folder - just the target URL is different).

And lastly option for the documents folder might be to use hidden files for stuff you don't want users to touch. iOS will hide any file that starts with dot, for example .hidden.txt. Although there is no guarantee that in the future these won't become available.

   

Thanks for the additional info.

   

Hacking with Swift is sponsored by RevenueCat

SPONSORED In-app subscriptions are a pain to implement, hard to test, and full of edge cases. RevenueCat makes it straightforward and reliable so you can get back to building your app. Oh, and it's free if your app makes less than $10k/mo.

Learn more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.