0

Update: Filed feedback FB12498822


I'm exploring SwiftData before migrating some existing apps using Core Data. However, I'm not even able to implement this simple action. What I'm trying to accomplish is to let the user choose multiple items from a list, then use a delete button to delete those items from the database. I'm starting off using Xcode's SwiftData project template, then added support for multi-selection and a delete button.

Item.swift

@Model
final class Item {
    var title: String
    var id: String
    
    init(title: String) {
        self.title = title
        self.id = UUID().uuidString
    }
}

extension Item: Identifiable {}

ContentView.swift

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var items: [Item]
    @State private var selection: Set<Item.ID> = []
    
    var body: some View {
        NavigationView {
            List(selection: $selection) {
                ForEach(items) { item in
                    Text(item.title)
                }
                .onDelete(perform: deleteItems)
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    EditButton()
                }
                ToolbarItem {
                    Button(action: addItem) {
                        Label("Add Item", systemImage: "plus")
                    }
                }
                ToolbarItem {
                    Button(action: deleteSelectedItems) {
                        Label("Delete", systemImage: "trash")
                    }
                }
            }
            Text("Select an item")
        }
    }

    private func deleteSelectedItems() {
        selection
            .compactMap { id in
                let predicate = #Predicate<Item> { $0.id == id }
                let descriptor = FetchDescriptor(predicate: predicate)
                let items = try? modelContext.fetch(descriptor)
                return items?.first
            }
            .forEach { modelContext.delete($0) }
        
    }

    private func addItem() {
        withAnimation {
            let newItem = Item(title: "New Item")
            modelContext.insert(newItem)
        }
    }

    private func deleteItems(offsets: IndexSet) {
        withAnimation {
            for index in offsets {
                modelContext.delete(items[index])
            }
        }
    }
}    

Every time when I tried to delete selected items using the delete button, it crashed on the @PersistedProperty macro of the id property of Item. However, it runs ok if I delete individual item by swiping the row.

Crashed on Item.id.getter

Not sure if I'm doing something wrong or is it a bug in the currently beta version of SwiftData. Appreciate if anyone could point me to the right direction.

Anthony
  • 747
  • 1
  • 8
  • 23

0 Answers0