将核心数据结构导出到附加到邮件的 .csv 文件 XCODE 8.1 Swift 3

Exporting Core Data structure to .csv file attached to mail XCODE 8.1 Swift 3

我正在制作一个应用程序,它需要从核心数据中获取一个托管对象数组并将其导出到一个 csv 文件,我计划将该文件附加到使用 mfMailComposer 系统发送的电子邮件中。我将数据正确存储在核心数据系统中,并且邮件编辑器功能似乎可以正常工作。当我试图找到导出数据的正确过程时遇到了障碍。

我已经仔细研究了这两个 post 试图确定解决方案:

从 2012 年开始,似乎非常过时: how to export Core Data to CSV

从 2016 年开始,最近,但是 swift 3 和 Xcode 8 已经发布,我担心这也已经过时了:

我一直在尝试尝试第二个 link 中提出的解决方案,但是大部分代码在输入时都被标记为不正确,所以我相信它现在已经随着升级而过时了。

下面的代码基于第二个 post,因此可能已过时,但为了提供我正在尝试完成的过程的参考...

// Called by the press of xcode UI button
@IBAction func ExportToCSV(_ sender: AnyObject)
{
    // Make our mail composer controller and fill it with the proper information
    let mailComposeViewController = configuredMailComposeViewController()

    // If the composer is functioning properly ...
    if MFMailComposeViewController.canSendMail()
    {
        // ... Present the generated mail composer controller
        self.present(mailComposeViewController, animated: true, completion: nil)
    }
    else
    {
        // ... Otherwise, show why it is not working properly
        self.showSendMailErrorAlert()
    }


}

// Used to set up the body of the outgoing email
func configuredMailComposeViewController() -> MFMailComposeViewController
{
    // Establish the controller from scratch
    let mailComposerVC = MFMailComposeViewController()
    mailComposerVC.mailComposeDelegate = self

    // Set preset information included in the email
    mailComposerVC.setSubject("Generic email subject")
    mailComposerVC.setMessageBody("Generic email body", isHTML: false)

    // Turn core data for responses into a .csv file

    // Pull core data in
    var CoreDataResultsList = [NSManagedObject]()

    // Register the proper delegate and managed context
    let appDelegate =
        UIApplication.shared.delegate as! AppDelegate

    let managedContext = appDelegate.managedObjectContext

    // Pull the data from core data
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "ItemResponses")
    do {
        let results =
            try managedContext!.fetch(fetchRequest)
        CoreDataResultsList = results as! [NSManagedObject]
    } catch let error as NSError {
        print("Could not fetch \(error), \(error.userInfo)")
    }

    // Take the managed object array and turn it into a .csv sring to write in the file
    let csvString = writeCoreObjectsToCSV(objects: CoreDataResultsList, named: "Generic name")
    let data = csvString.dataUsingEncoding(NSUTF8StringEncoding)
    mailComposerVC.addAttachmentData(data, mimeType: "text/csv", fileName: "GenericFilename.csv")

    return mailComposerVC
}

// Takes a managed object and writes it to the .csv file ..?
func writeCoreObjectsToCSV(objects: [NSManagedObject], named: String) -> String
{
    // Make sure we have some data to export
    guard objects.count > 0 else
    {

        return ""
    }
    let firstObject = objects[0]
    let attribs =  Array(firstObject.entity.attributesByName.keys)

    // The attires.reduce function is throwing an error about originally using combine as in the second post, used auto fix, but noteworthy. 
    //Now gives an error that says "No '+' candidates produce the expected contextual result type NSString"
    let csvHeaderString = (attribs.reduce("", {([=12=] as String) + "," +  }) as NSString).substringFromIndex(1) + "\n"

    // This function says that substring from index has been renamed as well as a few other lines within it
    let csvArray = objects.map({object in
        (attribs.map({((object.valueForKey([=12=]) ?? "NIL") as AnyObject).description}).reduce("",combine: {[=12=] + "," + }) as NSString).substringFromIndex(1) + "\n"
    })

    // Again with the reduce issue
    let csvString = csvArray.reduce("", combine: +)

    return csvHeaderString + csvString
}

新代码的底部我在第二个 post 的建议代码中评论的多个错误以及使用 xCode 的自动修复功能后的相关问题。

在此先感谢您帮助我解决这个问题。我只是在寻找将核心数据导出为 .csv 文件并将其发送出去的最新方法。谢谢!

我最终解决了这个问题。起初我不明白 .csv 文件是怎么写的,直到我看到 "comma-separated values" 的缩写。然后一切都为我点击了,我自己写了,我为头部条目做了一个更手动的路线,但以下几行的数据仍然是自动的。

以下是新工作形式的相关函数:

// Called by the press of xcode UI button
@IBAction func ExportToCSV(_ sender: AnyObject)
{
    // Make our mail composer controller and fill it with the proper information
    let mailComposeViewController = configuredMailComposeViewController()

    // If the composer is functioning properly ...
    if MFMailComposeViewController.canSendMail()
    {
        // ... Present the generated mail composer controller
        self.present(mailComposeViewController, animated: true, completion: nil)
    }
    else
    {
        // ... Otherwise, show why it is not working properly
        self.showSendMailErrorAlert()
    }


}

// Used to set up the body of the outgoing email
func configuredMailComposeViewController() -> MFMailComposeViewController
{
    // Establish the controller from scratch
    let mailComposerVC = MFMailComposeViewController()
    mailComposerVC.mailComposeDelegate = self

    // Set preset information included in the email
    mailComposerVC.setSubject("Generic Subject")
    mailComposerVC.setMessageBody("Generic Email Body", isHTML: false)

    // Turn core data for responses into a .csv file

    // Pull core data in
    var CoreDataResultsList = [NSManagedObject]()

    // Register the proper delegate and managed context
    let appDelegate =
        UIApplication.shared.delegate as! AppDelegate

    let managedContext = appDelegate.managedObjectContext

    // Pull the data from core data
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "ItemResponses")
    do {
        let results =
            try managedContext!.fetch(fetchRequest)
        CoreDataResultsList = results as! [NSManagedObject]
    } catch let error as NSError {
        print("Could not fetch \(error), \(error.userInfo)")
    }

    // Take the managed object array and turn it into a .csv sring to write in the file
    // In doing this, we are writing just like we would to any string
    let csvString = writeCoreObjectsToCSV(objects: CoreDataResultsList)
    let data = csvString.data(using: String.Encoding.utf8.rawValue, allowLossyConversion: false)
    mailComposerVC.addAttachmentData(data!, mimeType: "text/csv", fileName: "GenericFilename.csv")

    return mailComposerVC
}

// Takes a managed object and writes it to the .csv file ..?
func writeCoreObjectsToCSV(objects: [NSManagedObject]) -> NSMutableString
{
    // Make sure we have some data to export
    guard objects.count > 0 else
    {

        return ""
    }

    var mailString = NSMutableString()


    mailString.append("Generic Header 1, Generic Header 2, Generic Header 3")

    for object in objects
    {
        // Put "\n" at the beginning so you don't have an extra row at the end
        mailString.append("\n\(object.value(forKey: "Generic Core Data Key 1")!),\(object.value(forKey: "Generic Core Data Key 2")!), \(object.value(forKey: "Generic Core Data Key 3")!)")
    }
    return mailString
}

我遇到一个问题,我的一个键是包含逗号的字符串,需要一种正确的方法来避开它们。我听说双引号是怎么做的,但是插入它们没有成功。

无论如何,这是将核心数据放入数组并将其写入字符串、保存到 .csv 文件并邮寄出去的一种当前方法。这回答了我的问题,但我的下一个任务是读回数据。我不知道如何访问文件以在 iPad 上执行此操作。如果您遇到此问题并知道该怎么做,请告诉我!如果找不到解决方案,我可能会就该主题再做一个 post,然后在这个答案下面的回复中提出一个新问题和一个 link。

谢谢!