Экспорт CoreData в CSV в Swift - PullRequest
       5

Экспорт CoreData в CSV в Swift

1 голос
/ 12 января 2020

Я хочу, чтобы пользователь мог экспортировать все свои записи CoreData "DiaryItem" в CSV. Вот мой код:

DiaryItem.swift

import Foundation
import CoreData

public class DiaryItem:NSManagedObject,Identifiable {
   @NSManaged public var createdAt:Date?
   @NSManaged public var title:String?
}

extension DiaryItem {
    static func getAllDiaryItems() -> NSFetchRequest<DiaryItem> {
        let request:NSFetchRequest<DiaryItem> = DiaryItem.fetchRequest() as! NSFetchRequest<DiaryItem>

        let sortDescriptor = NSSortDescriptor(key: "createdAt", ascending: true)

        request.sortDescriptors = [sortDescriptor]

        return request
     }
}

SettingsView.swift

    import SwiftUI
    import CoreData

    struct SettingsView: View {
    @FetchRequest(entity: DiaryItem.entity(), sortDescriptors: [
        NSSortDescriptor(keyPath: \DiaryItem.createdAt, ascending: false),
    ]) var diaryItems : FetchedResults<DiaryItem>

    var body: some View {
        VStack(alignment: .leading) {
            Button(action: {
                  self.exportDatabase()
               }) {
                  Text("Export")
                  }
        }
    }

    func exportDatabase() {
        let exportString = createExportString()
        saveAndExport(exportString: exportString)
    }

    func saveAndExport(exportString: String) {
        let exportFilePath = NSTemporaryDirectory() + "itemlist.csv"
        let exportFileURL = NSURL(fileURLWithPath: exportFilePath)
        FileManager.default.createFile(atPath: exportFilePath, contents: NSData() as Data, attributes: nil)
        //var fileHandleError: NSError? = nil
        var fileHandle: FileHandle? = nil
        do {
            fileHandle = try FileHandle(forWritingTo: exportFileURL as URL)
        } catch {
            print("Error with fileHandle")
        }

       if fileHandle != nil {
            fileHandle!.seekToEndOfFile()
            let csvData = exportString.data(using: String.Encoding.utf8, allowLossyConversion: false)
        fileHandle!.write(csvData!)

        fileHandle!.closeFile()

        let firstActivityItem = NSURL(fileURLWithPath: exportFilePath)
        let activityViewController : UIActivityViewController = UIActivityViewController(
            activityItems: [firstActivityItem], applicationActivities: nil)

        activityViewController.excludedActivityTypes = [
            UIActivity.ActivityType.assignToContact,
            UIActivity.ActivityType.saveToCameraRoll,
            UIActivity.ActivityType.postToFlickr,
            UIActivity.ActivityType.postToVimeo,
            UIActivity.ActivityType.postToTencentWeibo
        ]
    }
}

func createExportString() -> String {
    var createdAt: Date?
    var title: String?

    var export: String = NSLocalizedString("createdAt, title \n", comment: "")
    for diaryItem in self.diaryItems {

            let createdAtvar = DiaryItem.value(forKey: "createdAt") as! Date?
            let titlevar = DiaryItem.value(forKey: "title") as! String?
            let createdAtString = createdAtvar
            let titleString = titlevar

            export += "\(titleString!),\(createdAtString!)\n"

    }
    print("This is what the app will export: \(export)")
    return export
    }
   }
}

К сожалению, когда я запускаю в симуляторе происходит сбой с ошибкой:

[SwiftUI] Контекст в среде не связан с постоянным координатором хранилища:

Я бился головой против этого в течение многих часов любая помощь будет чрезвычайно цениться !!

1 Ответ

1 голос
/ 09 февраля 2020

Чтобы улучшить свой код, попробуйте заменить:

struct SettingsView: View {
    @FetchRequest(entity: DiaryItem.entity(), sortDescriptors: [
        NSSortDescriptor(keyPath: \DiaryItem.createdAt, ascending: false),
    ]) var diaryItems : FetchedResults<DiaryItem>

    var body: some View {

на:

struct SettingsView: View {
    @Environment(\.managedObjectContext) var moc
    @FetchRequest(fetchRequest: DiaryItem.getAllDiaryItems()) var diaryItems: FetchedResults<DiaryItem>

    var body: some View {

Вы создали способ простого извлечения данных из управляемого объекта, но вы делаете в любом случае это вручную в окне настроек - используйте .getAllDiaryItems, чтобы получить выборку. у вас вообще нет контекста управляемого объекта в файле - это то, как файл связывается с базой данных.

Надеюсь, это поможет.

Тахмид

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...