SwiftUI - 将核心数据导出到 CSV 文件 - 无法迭代实体

mal*_*low 0 csv core-data ios swift swiftui

我正在使用 SwiftUI 编写一个应用程序。我正在尝试将核心数据中一个实体(NPTransactions、属性:日期(Date)、类型(String))的所有条目导出到 CSV 文件中。我想使用共享表,这样用户就可以将文件保存到他们的手机上。

我知道该怎么做是: - 创建 CSV 文件 - 保存 CSV 文件 - 打开共享表

问题是: 我不知道如何迭代实体条目并在 CSV 文件中创建新的文本行。

我想从我的实体创建一个数组,如下所示:

var transactions = [NPTransaction]()
Run Code Online (Sandbox Code Playgroud)

后来我希望迭代这个数组并为每个条目添加新的文本行。但这不起作用。此 for 循环中没有添加任何文本。

我的代码是这样的:

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()
    }
}
Run Code Online (Sandbox Code Playgroud)

是我的 for 循环有问题还是我应该采用不同的方式?例如以某种方式使用 fetchRequest ?

mal*_*low 8

尤里卡!:) 我错过了一个@FetchRequest:

@FetchRequest(entity: NPTransaction.entity(), sortDescriptors: []) var transactions: FetchedResults<NPTransaction>
Run Code Online (Sandbox Code Playgroud)

完整代码如下。也许对其他人有用。

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()
    }
}
Run Code Online (Sandbox Code Playgroud)