The deletion is working, but it does not refresh the view. This is similar to a question I asked previously but I started a new test project to try and work this out.
@Model
class Transaction {
var timestamp: Date
var note: String
@Relationship(deleteRule: .cascade) var items: [Item]?
init(timestamp: Date, note: String, items: [Item]? = nil) {
self.timestamp = timestamp
self.note = note
self.items = items
}
func getModifierCount() -> Int {
guard let items = items else { return 0 }
return items.reduce(0, {result, item in
result + (item.modifiers?.count ?? 0)
})
}
}
@Model
class Item {
var timestamp: Date
var note: String
@Relationship(deleteRule: .nullify) var transaction: Transaction?
@Relationship(deleteRule: .noAction) var modifiers: [Modifier]?
init(timestamp: Date, note: String, transaction: Transaction? = nil, modifiers: [Modifier]? = nil) {
self.timestamp = timestamp
self.note = note
self.transaction = transaction
self.modifiers = modifiers
}
}
@Model
class Modifier {
var timestamp: Date
var value: Double
@Relationship(deleteRule: .nullify) var items: [Item]?
init(timestamp: Date, value: Double, items: [Item]? = nil) {
self.timestamp = timestamp
self.value = value
self.items = items
}
}
struct ContentView: View {
@Environment(\.modelContext) private var context
@Query private var items: [Item]
@Query private var transactions: [Transaction]
@Query private var modifiers: [Modifier]
@State private var addItem = false
@State private var addTransaction = false
var body: some View {
NavigationStack {
List {
Section(content: {
ForEach(items) { item in
LabeledText(label: item.timestamp.formatAsString(), value: .int(item.modifiers?.count ?? -1))
}
.onDelete(perform: { indexSet in
withAnimation {
for index in indexSet {
context.delete(items[index])
}
}
})
}, header: {
LabeledView(label: "Items", view: {
Button("", systemImage: "plus", action: {})
})
})
Section(content: {
ForEach(modifiers) { modifier in
LabeledText(label: modifier.timestamp.formatAsString(), value: .currency(modifier.value))
}
.onDelete(perform: { indexSet in
indexSet.forEach { index in
context.delete(modifiers[index])
}
})
}, header: {
LabeledView(label: "Modifiers", view: {
Button("", systemImage: "plus", action: {})
})
})
Section(content: {
ForEach(transactions) { transaction in
LabeledText(label: transaction.note, value: .int(transaction.getModifierCount()))
}
.onDelete(perform: { indexSet in
withAnimation {
for index in indexSet {
context.delete(transactions[index])
}
}
})
}, header: {
LabeledView(label: "Transactions", view: {
Button("", systemImage: "plus", action: {addTransaction.toggle()})
})
})
}
.navigationTitle("Testing")
.sheet(isPresented: $addTransaction, content: {
TransactionEditor()
})
}
}
}
}
Here's the scenario. Create a transaction with 1 item. That item will contain 1 modifier. ContentView will display Items, Modifiers, and Transactions. For Item, it will display the date and how many modifiers it has. Modifier will display the date and its value. Transactions will display a date and how many modifiers are contained inside of its items.
When I delete a modifier, in this case the only one that exist, I should see the count update to 0 for both the Item and the Transaction. This is not happening unless I close the application and reopen it. If I do that, it's updated to 0. I tried to add an ID variable to the view and change it to force a refresh, but it's not updating.
This issue also seems to be only with this many to many relationship. Previously, I only had the Transaction and Item models. Deleting an Item would correctly update Transaction, but that was a one to many relationship.
I would like for Modifier to have a many to many relationship with Items, so they can be reused.
Why is deleting a modifier not updating the items correctly? Why is this not refreshing the view? How can I resolve this issue?