SwiftUI Blog

Mastering SwiftUI: Your Guide to Building Beautiful, Intuitive Apps.

SwiftData – Episode II° – Delete

In this episode, we’ll learn how to delete data.

Let’s start with deletion in the projects (I advise you to take a look at the previous episode because I will start from that code). The first step is to ensure that when we delete a project, we also delete all the pomodoros for that project in cascade. To do that, we need to make some small changes to the ProjectItem definition.

import Foundation
import SwiftData

@Model
final class ProjectItem: Identifiable {
    var name: String
    var id = UUID().uuidString

    @Relationship(deleteRule: .cascade, inverse: \PomodoroItem.project)
    var pomodori = [PomodoroItem]()
    
    init(name: String) {
        self.name = name
    }
}

We add a @Relationship attribute for the deletion on the list of pomodoros associated with the project. The deletion will be in cascade, considering the inverse relationship that we have in the PomodoroItem (where we have project: ProjectItem) as you can see in the code:

import Foundation
import SwiftData

@Model
final class PomodoroItem {
    var start: Date
    var end: Date
    var project: ProjectItem
    var name: String
    
    init(start: Date, end: Date, project: ProjectItem, name: String) {
        self.start = start
        self.end = end
        self.project = project
        self.name = name
    }
}

Now take a look at the ProjectsView:

import SwiftUI
import SwiftData

struct ProjectsView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var projects: [ProjectItem]

    var body: some View {
        NavigationStack {
            List {
                ForEach(projects) { project in
                    Text(project.name)
                }.onDelete(perform: deleteProject)
            }
            .toolbar {
                ToolbarItem {
                    Button(action: {isPresented = true}) {
                        Label("Add Project", systemImage: "plus")
                    }
                
                ToolbarItem(placement: .navigationBarTrailing) {
                    EditButton()
                } 
            }.sheet(isPresented: $isPresented, content: {
                ProjectView()
            })
        }
    }
    private func deleteProject(offsets: IndexSet) {
        withAnimation {
            for index in offsets {
                modelContext.delete(projects[index])
            }
        }
    }
}

We added an EditButton to the toolbar (one of the special buttons in SwiftUI). Tapping on this button will display the buttons to delete the rows. When you tap on one of these buttons, the deleteProjectFunction is called to delete the project.

The view for the pomodoros is similar:

struct PomodoriView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var pomodori: [PomodoroItem]
    @State var isPresented = false
    
    var body: some View {
        NavigationStack {
            List {
                ForEach(pomodori) { pomodoro in
                    Text(pomodoro.name)
                }.onDelete(perform: deletePomodoro)
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    EditButton()
                }
                ToolbarItem {
                    Button(action: {isPresented = true}) {
                        Label("Add Pomodoro", systemImage: "plus")
                    }
                }
            }.sheet(isPresented: $isPresented, content: {
                PomodoroView()
            })
        }
    }
    private func deletePomodoro(offsets: IndexSet) {
        withAnimation {
            for index in offsets {
                modelContext.delete(pomodori[index])
            }
        }
    }
}

This tutorial may seem short, but I encourage you to experiment with deletion and relationships.

Leave a Reply

Your email address will not be published. Required fields are marked *