0

I am writing an app using SwiftUI. I am trying to export all entries of one Entity (NPTransactions, attributes: date (Date), type(String)) in Core Data into CSV file. I want to use Share Sheet, so users could for example save the file to their phones.

What I know how to do is: - create CSV file - save CSV file - open Share Sheet

The problem is: I don't know how to iterate through Entity entries and create new line of text in CSV file.

I wanted to create an array from my entity like this:

var transactions = [NPTransaction]()

Later on I was hoping to iterate through this array and add new line of text for every entry. But it doesn't work. No text is being added from this for loop.

My code is like this:

import SwiftUI

struct SettingsView: View {

    @State private var isShareSheetShowing = false

    var transactions = [NPTransaction]()

    var body: some View {
        NavigationView {
            Button(action: shareButton)
            {
                HStack(alignment: .firstTextBaseline) {
                    Text("Export CSV")
                        .font(.headline)
                    Image(systemName: "square.and.arrow.up")
                        .font(.title)
                }
            }
        }
        .navigationBarTitle("Settings")
    }

    func shareButton() {
        let fileName = "export.csv"
        let path = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(fileName)
        var csvText = "Date,Type\n"

        // This test works
        //      for _ in 1...5 {
        //          csvText += "test 1, test 2\n"
        //      }

        // This doesn't work
        for transaction in transactions {
            csvText += "\(transaction.date ?? Date()),\(transaction.type ?? "-")\n"
        }           

        do {
            try csvText.write(to: path!, atomically: true, encoding: String.Encoding.utf8)
        } catch {
            print("Failed to create file")
            print("\(error)")
        }
        print(path ?? "not found")

        var filesToShare = [Any]()
        filesToShare.append(path!)

        let av = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)

        UIApplication.shared.windows.first?.rootViewController?.present(av, animated: true, completion: nil)

        isShareSheetShowing.toggle()
    }

}

struct SettingsView_Previews: PreviewProvider {
    static var previews: some View {
        SettingsView()
    }
}

Is the problem with my for loop or should I make it a different way? For example using fetchRequest somehow?

4
  • 1
    The array is empty. You have to fetch the data somewhere. Commented Jun 11, 2020 at 6:58
  • Thanks. Yes. And I don’t know how to do it correctly. Examples I have found are old or not from SwiftUI and I couldn’t make them work Commented Jun 11, 2020 at 6:59
  • Fetching the data is not particularly related to SwiftUI. And if you are dealing with CoreData you must know how to fetch data. Commented Jun 11, 2020 at 7:04
  • Thanks, vadian. Your answer helped me to fix it :) Commented Jun 11, 2020 at 8:56

1 Answer 1

8

Eureka! :) I was missing a @FetchRequest:

@FetchRequest(entity: NPTransaction.entity(), sortDescriptors: []) var transactions: FetchedResults<NPTransaction>

Full code below. Maybe it will be useful for someone else.

import SwiftUI

struct SettingsView: View {

    @FetchRequest(entity: NPTransaction.entity(), sortDescriptors: []) var transactions: FetchedResults<NPTransaction>
    @State private var isShareSheetShowing = false

    var body: some View {
        NavigationView {
            Button(action: shareButton)
            {
                HStack(alignment: .firstTextBaseline) {
                    Text("Export CSV")
                        .font(.headline)
                    Image(systemName: "square.and.arrow.up")
                        .font(.title)
                }
            }
        }
        .navigationBarTitle("Settings")
    }

    func shareButton() {
        let fileName = "export.csv"
        let path = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(fileName)
        var csvText = "Date,Type\n"

        for transaction in transactions {
            csvText += "\(transaction.date ?? Date()),\(transaction.type ?? "-")\n"
        }

        do {
            try csvText.write(to: path!, atomically: true, encoding: String.Encoding.utf8)
        } catch {
            print("Failed to create file")
            print("\(error)")
        }
        print(path ?? "not found")

        var filesToShare = [Any]()
        filesToShare.append(path!)

        let av = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)

        UIApplication.shared.windows.first?.rootViewController?.present(av, animated: true, completion: nil)

        isShareSheetShowing.toggle()
    }

}

struct SettingsView_Previews: PreviewProvider {
    static var previews: some View {
        SettingsView()
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.