macosswiftuiswiftdata

How to add a delete button to for swift data items?


I’m working on a macOS application. I have a list of SwiftData items. Something like this:

struct TestDataList: View {
    @Query var allTestData: [TestData]

    var body: some View {
        VStack {
            Text("Everything")
            if allTestData.count > 0 {
                List {
                    ForEach(allTestData){ test in
                        HStack {
                            Text(test.id)
                            Spacer()
                            Text(test.value)
                            Spacer()
                            Button("", systemImage: "trash", action: {
                                //  ?
                            })
                        }
                    }
                }
            }
        }
        .modelContainer(for: TestData.self)
    }
}

I would like to add a button which will delete the current item.

I have searched around, but everything is for iOS, and I can’t see how it would apply here.

What action code do I need to delete the current item, both from the List, and, more importantly from the data?


Solution

  • Try this approach, using modelContext and the TestData to delete. Tested on real mac, MacOS 15.2 not Preview.

    Note, no need for the if allTestData.count > 0 {

    Here is the full code that works on macOS.

    struct ContentView: View {
        var body: some View {
            TestDataList()
        }
    }
    
    struct TestDataList: View {
        @Environment(\.modelContext) private var modelContext // <--- here
        
        @Query var allTestData: [TestData]
        
        var body: some View {
            VStack {
                // for testing, to add a few test data
                Button(action: addItem) {
                    Label("Add Item", systemImage: "plus")
                }.buttonStyle(.bordered)
                
                Text("Everything")
                List {
                    ForEach(allTestData){ test in
                        HStack {
                            Text(test.id)
                            Spacer()
                            Text(test.value)
                            Spacer()
                            Button("", systemImage: "trash", action: {
                                modelContext.delete(test) // <--- here
                            })
                        }
                    }
                }
            }
        }
        
        private func addItem() {
            withAnimation {
                let randm = String(UUID().uuidString.prefix(5))
                let newItem = TestData(id: randm, value: randm)
                modelContext.insert(newItem)
            }
        }
    }
    
    
    @Model
    class TestData {
        @Attribute(.unique) var id: String
        var value: String
        
        init(id: String, value: String) {
            self.id = id
            self.value = value
        }
    }
    
    @main
    struct TestApp: App {
        var sharedModelContainer: ModelContainer = {
            let schema = Schema([
                TestData.self,
            ])
            let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
    
            do {
                return try ModelContainer(for: schema, configurations: [modelConfiguration])
            } catch {
                fatalError("Could not create ModelContainer: \(error)")
            }
        }()
    
        var body: some Scene {
            WindowGroup {
                ContentView()
            }
            .modelContainer(sharedModelContainer)
        }
    }