Basic CRUD operations in Core Data

>In this article, we will explore how to perform basic CRUD (Create, Read, Update, Delete) operations using Core Data in a SwiftUI application.

article

In this article, we will explore how to perform basic CRUD (Create, Read, Update, Delete) operations using Core Data in a SwiftUI application. CRUD operations are essential when building data-driven apps, allowing you to interact with your app’s data by creating new entries, reading and displaying data, updating existing data, and deleting unwanted records. We’ll walk through each of these operations with practical SwiftUI examples.


Create: Adding New Data to Core Data

To add new data to Core Data in SwiftUI, you create a new instance of the desired entity (in this case, a "Task" entity), populate its attributes, and save the changes using the NSManagedObjectContext. Here's an example of how to add a new task to Core Data:



struct AddTaskView: View {
    @Environment(\.managedObjectContext) private var viewContext
    @State private var taskName = ""

    var body: some View {
        VStack {
            TextField("Enter task name", text: $taskName)
                .padding()

            Button("Add Task") {
                addTask()
            }
            .padding()
        }
        .padding()
    }

    private func addTask() {
        let newTask = Task(context: viewContext)
        newTask.name = taskName

        do {
            try viewContext.save()
            print("Task added successfully!")
        } catch {
            print("Failed to save task: \(error.localizedDescription)")
        }
    }
}

In this example, the user enters a task name into a TextField, and when they press the "Add Task" button, a new task is created and saved to the persistent store. The Core Data context (viewContext) is used to create and manage the task before saving.


Read: Fetching and Displaying Data from Core Data

Fetching data from Core Data in SwiftUI is simple with the @FetchRequest property wrapper. This automatically fetches data from the persistent store and updates the SwiftUI views when the data changes. Here's an example of how to display a list of tasks stored in Core Data:



struct TaskListView: View {
    @FetchRequest(
        entity: Task.entity(),
        sortDescriptors: [NSSortDescriptor(keyPath: \Task.name, ascending: true)]
    ) private var tasks: FetchedResults

    var body: some View {
        List {
            ForEach(tasks) { task in
                Text(task.name ?? "Unknown Task")
            }
        }
    }
}

In this example, the @FetchRequest fetches all tasks from the Core Data store and displays them in a SwiftUI List. The fetch request sorts the tasks by name in ascending order, and the list automatically updates when the data changes.


Update: Editing Existing Data

Updating existing data in Core Data with SwiftUI involves fetching the object you want to modify, changing its properties, and saving the changes. Here's an example of how to update a task:



struct EditTaskView: View {
    @Environment(\.managedObjectContext) private var viewContext
    @Binding var task: Task
    @State private var taskName: String = ""

    var body: some View {
        VStack {
            TextField("Edit task name", text: $taskName)
                .padding()

            Button("Save Changes") {
                updateTask()
            }
            .padding()
        }
        .onAppear {
            taskName = task.name ?? ""
        }
    }

    private func updateTask() {
        task.name = taskName

        do {
            try viewContext.save()
            print("Task updated successfully!")
        } catch {
            print("Failed to update task: \(error.localizedDescription)")
        }
    }
}

In this example, the task to be edited is passed into the view via a @Binding. The user can edit the task's name, and when they press "Save Changes," the task is updated in Core Data. The changes are persisted by calling viewContext.save().


Delete: Removing Data from Core Data

Deleting data from Core Data in SwiftUI is simple and is typically handled within a List using the onDelete modifier. Here's an example of how to allow users to swipe to delete tasks:



struct TaskListView: View {
    @Environment(\.managedObjectContext) private var viewContext
    @FetchRequest(
        entity: Task.entity(),
        sortDescriptors: [NSSortDescriptor(keyPath: \Task.name, ascending: true)]
    ) private var tasks: FetchedResults

    var body: some View {
        List {
            ForEach(tasks) { task in
                Text(task.name ?? "Unknown Task")
            }
            .onDelete(perform: deleteTasks)
        }
    }

    private func deleteTasks(offsets: IndexSet) {
        offsets.map { tasks[$0] }.forEach(viewContext.delete)

        do {
            try viewContext.save()
        } catch {
            print("Failed to delete task: \(error.localizedDescription)")
        }
    }
}

Here, the onDelete modifier enables swipe-to-delete functionality. When the user swipes and deletes a task, the task is removed from the managed object context and then the context is saved to persist the changes.


Conclusion

Understanding and implementing CRUD operations in Core Data with SwiftUI is essential for building data-driven apps. SwiftUI’s property wrappers like @FetchRequest and @Environment make it easy to integrate Core Data’s powerful persistence capabilities with a modern, declarative UI. In this article, we covered how to create, read, update, and delete data in Core Data with SwiftUI.


In this article, we explored how to perform basic CRUD operations with Core Data in SwiftUI, allowing you to create, read, update, and delete data in your app. These fundamental operations are critical for any app that deals with persistent data. In the next article, we’ll dive deeper into advanced data fetching techniques and how to optimize your SwiftUI app when working with large datasets in Core Data.

instructor

Exodai INSTRUCTOR!

Johan t'Sas

Owner and Swift developer!