Setting up Core Data with SwiftUI

In this article, we will walk through how to set up Core Data in an iOS project, step by step. Core Data provides a robust data management layer

article

In this article, we will walk through how to set up Core Data in a SwiftUI project. Core Data is a powerful framework for data management and persistence, and with SwiftUI, you can seamlessly integrate Core Data into your modern, declarative user interface. By the end of this article, you'll have Core Data set up in a SwiftUI project, with a clear understanding of how to manage and persist data using the tools provided by SwiftUI and Core Data together.


Step 1: Enabling Core Data in a New SwiftUI Project

Setting up Core Data in a SwiftUI project is straightforward, as Xcode provides built-in support. Follow these steps to get started:


  • Open Xcode and click Create a new Xcode project.
  • Choose App under the iOS tab and click Next.
  • Give your project a name, select your team, and choose your desired settings.
  • Check the Use Core Data option before clicking Next.
  • Choose a location to save your project, then click Create.

By enabling Core Data, Xcode generates a default Core Data stack for you and adds a .xcdatamodeld file where you can define your data model. Xcode also automatically sets up the Core Data stack in the app’s lifecycle when using the SwiftUI App protocol.


Step 2: Setting Up the Core Data Stack in SwiftUI

When you create a new SwiftUI project with Core Data enabled, Xcode will automatically include a Core Data stack in your project. This stack includes the NSPersistentContainer that is responsible for managing the Core Data environment. Here’s a look at how the Core Data stack is typically set up in SwiftUI:



// In your SwiftUI App struct (usually App.swift file)

import SwiftUI
import CoreData

@main
struct MyCoreDataApp: App {
    let persistentContainer = PersistenceController.shared
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(\.managedObjectContext, persistentContainer.viewContext)
        }
    }
}

In the code above, the Core Data stack is initialized and passed into the SwiftUI environment using the .environment modifier. This makes the managed object context available throughout the app, allowing you to interact with Core Data seamlessly in your SwiftUI views.


Step 3: Using Core Data in SwiftUI Views

Once the managed object context is available in your app’s environment, you can access it in any SwiftUI view. For example, you can use the @Environment property wrapper to access the Core Data context in your view like this:



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

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

            Button(action: addTask) {
                Text("Add Task")
            }
        }
        .padding()
    }

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

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

In this example, we use the @Environment property wrapper to inject the Core Data context into our ContentView. When the user enters a task name and clicks the "Add Task" button, a new task is created and saved to the persistent store using Core Data.


Step 4: Fetching Data with Core Data in SwiftUI

In SwiftUI, you can easily fetch data from Core Data using the @FetchRequest property wrapper. This allows you to fetch and display Core Data objects in a SwiftUI view without needing to manually handle the fetch requests. Here’s how you can fetch and display tasks from Core Data:



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")
            }
        }
    }
}

In this code, @FetchRequest fetches all the tasks from Core Data and sorts them by their name. The fetched results are automatically updated whenever there are changes to the data, and SwiftUI handles the UI updates for you.


Step 5: Deleting Data in SwiftUI with Core Data

To delete data in SwiftUI using Core Data, you can take advantage of SwiftUI’s built-in onDelete modifier in lists. Here’s how you can allow users to swipe to delete a task:



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 provides the swipe-to-delete functionality for tasks. When a task is deleted, the Core Data context is updated and saved, and the list automatically reflects the changes.


Conclusion

Setting up Core Data in a SwiftUI project is simple, and once the Core Data stack is integrated with SwiftUI’s declarative framework, you can easily manage, fetch, and update data in your app. In this article, we covered how to enable Core Data in a SwiftUI project, interact with Core Data’s managed object context, and fetch and delete data using SwiftUI views. In the next article, we’ll dive deeper into how Core Data interacts with SwiftUI’s state management and explore more complex data handling scenarios.


In this article, we explored the process of setting up Core Data in a SwiftUI project and demonstrated how to create, fetch, and delete Core Data objects within SwiftUI views. Core Data and SwiftUI work well together, enabling powerful data management with minimal code. Next, we'll explore advanced topics like relationships, background context management, and performance optimization in Core Data with SwiftUI.

instructor

Exodai INSTRUCTOR!

Johan t'Sas

Owner and Swift developer!