Data Persistence and Core Data with SwiftUI

  • Is there an easy way to add Core Data persistence into an already built SwiftUI app?

I've been working through various SwiftUI tutorials to build a very simple reminders/to-do app for myself for the past couple of months. The functionality works, but every time I close the app, I lose the list of tasks. So I started delving into data persistence.

What I found is that Core Data seems to be the preferred method; however, it seems like MOST of the tutorials on Core Data are in conjunction with UIKit. Any Core Data tutorials with SwiftUI usually start with the beginning of the project, creating the models in Core Data from the beginning - not trying to implement them on the backend.

  • Is there a way to relate my already created "Task" struct to a Core Data model, such that I don't have to recreate everything? With an extension of Task maybe? Or an easy to way to copy my Task struct over to the Core Data model class/entity?

As a beginner, I'm probably approaching this completely wrong, so I'm happy to take a different approach if there's something more preferable.

import Foundation
import SwiftUI

struct Task: Identifiable, Hashable, Codable {

    let id: UUID
    var taskTitle: String
    var taskNotes: String
    var isTapped: Bool

    init(id:UUID = UUID(), taskTitle:String, taskNotes:String = "", isTapped:Bool = false) {
        self.id = id
        self.taskTitle = taskTitle
        self.taskNotes = taskNotes
        self.isTapped = isTapped
    }
}

extension Task {
    struct Data {
        var taskTitle:String = ""
        var taskNotes:String = ""
        var isTapped:Bool = false
    }

    var data: Data {
        Data(taskTitle: taskTitle, taskNotes: taskNotes, isTapped: isTapped)
    }
}
Answered by Razorback2424 in 724367022

Leaving this for anyone else that might be searching:

After tinkering with Core Data for a while and trying to get it set up, I ended up scrapping Core Data and using the FileManager system. I'm sure there's drawbacks to going this route versus going the Core Data route, but I'm only trying to store two relatively small arrays (less than 50 items for sure, probably less than 10 items in most cases) and a lot of the sorting is done in the app itself. So, it seemed like the easiest solution for now, as I was able to implement it in a few hours using my existing structs.

I used this as my guide, and tweaked slightly for my use case: https://developer.apple.com/tutorials/app-dev-training/persisting-data

While this looked intimidating at first, I found it to be infinitely easier than figuring out Core Data. Just my experience, but wanted to share my experience for anybody who finds this in the future.

This should help you: https://www.apps4world.com/add-core-data-swiftui-tutorial.html

If you haven't gone through this tutorial yourself and can't answer this question, that's perfectly fine, but I have one main question as I tried to work through that tutorial (note: I don't know the website and thus didn't feel comfortable downloading the sample project in Xcode):

Is the ultimate solution to replace their TodoItem struct (pre-created) with the Todo class generated by the Core Data Model (codegen when creating the entity/attributes)?

Core Data with SwiftUI

  • Create the Core Data container once when the app starts
  • Inject its managed object context into the environment
  • Perform fetch requests directly on there

NSManagedObject conforms to the ObservableObject protocol

  • which means we can bind any object to part of our user interface

There’s a managedObjectContext key in the environment

  • designed to store our active Core Data managed object context

We then inject that context into the initial content view.
There’s a @FetchRequest property wrapper

  • that uses the environment’s managed object context to perform fetch requests

You'll have to recreate your Task struct as an NSManagedObject, and it won't behave quite the same, so you'll have a bit of work to do.

"You'll have to recreate your Task struct as an NSManagedObject, and it won't behave quite the same, so you'll have a bit of work to do."

I think this was the reassurance I was looking for. This is what I believed to be true after playing around with the Core Data Model a little bit last night and this morning, but before I delved into changing it all around to use the NSManagedObject created through the Core Data Model codegen instead of my already created "Task" struct, wanted to make sure I was going down the right path or if there was an easier way.

I'm sure I'll run into some issues when you say it won't behave quite the same, but that's a problem for another day!

Thank you both for your replies!!

Accepted Answer

Leaving this for anyone else that might be searching:

After tinkering with Core Data for a while and trying to get it set up, I ended up scrapping Core Data and using the FileManager system. I'm sure there's drawbacks to going this route versus going the Core Data route, but I'm only trying to store two relatively small arrays (less than 50 items for sure, probably less than 10 items in most cases) and a lot of the sorting is done in the app itself. So, it seemed like the easiest solution for now, as I was able to implement it in a few hours using my existing structs.

I used this as my guide, and tweaked slightly for my use case: https://developer.apple.com/tutorials/app-dev-training/persisting-data

While this looked intimidating at first, I found it to be infinitely easier than figuring out Core Data. Just my experience, but wanted to share my experience for anybody who finds this in the future.

Good response.
I suggest you mark your post as the "correct" answer.
This will close the thread, and indicate that it contains useful information.

Data Persistence and Core Data with SwiftUI
 
 
Q