The reference of delete(model:where:includeSubclasses:) doesn't mention that behavior, and I believe that is because delete(model:where:includeSubclasses:) goes down directly to the store to delete the objects (for better performance), like what NSBatchDeleteRequest does, and doesn't discard the unsaved objects in the context.
Ahh… interesting! This is very valuable insight. Thanks! I am beginning to understand this behavior more.
A follow up question is I am still looking for one "single shot" function to delete all model instances (including staged and pending models prior to save). I can think of (at least) three options:
Explicitly save before attempting to delete all:
func testSaveAndDelete() throws {
let modelContext = ModelContext(container)
modelContext.insert(Item())
print(try modelContext.fetchCount(FetchDescriptor<Item>()) == 1)
modelContext.insert(Item())
print(try modelContext.fetchCount(FetchDescriptor<Item>()) == 2)
try modelContext.save()
try modelContext.delete(model: Item.self)
print(try modelContext.fetchCount(FetchDescriptor<Item>()) == 0)
}
Attempt to delete all and then follow up with an iteration through all remaining:
func testSaveAndDeleteAndIterate() throws {
let modelContext = ModelContext(container)
modelContext.insert(Item())
print(try modelContext.fetchCount(FetchDescriptor<Item>()) == 1)
try modelContext.save()
modelContext.insert(Item())
print(try modelContext.fetchCount(FetchDescriptor<Item>()) == 2)
try modelContext.delete(model: Item.self)
print(try modelContext.fetchCount(FetchDescriptor<Item>()) == 1)
for model in try modelContext.fetch(FetchDescriptor<Item>()) {
modelContext.delete(model)
}
print(try modelContext.fetchCount(FetchDescriptor<Item>()) == 0)
}
Iterate through all inserted models prior to delete all:
func testSaveAndIterateAndDelete() throws {
let modelContext = ModelContext(container)
modelContext.insert(Item())
print(try modelContext.fetchCount(FetchDescriptor<Item>()) == 1)
try modelContext.save()
modelContext.insert(Item())
print(try modelContext.fetchCount(FetchDescriptor<Item>()) == 2)
for model in modelContext.insertedModelsArray {
// TODO: filter only for `item` models! :D
modelContext.delete(model)
}
print(try modelContext.fetchCount(FetchDescriptor<Item>()) == 1)
try modelContext.delete(model: Item.self)
print(try modelContext.fetchCount(FetchDescriptor<Item>()) == 0)
}
All of these options seem to operate correctly and pass my tests. any opinion about which pattern might provide the right choice to optimize for memory and CPU? My intuition tells me the most efficient pattern might depend on the model schema and the state of this context at any point in time. Any more insight about what might be the right option here? Thanks!