Reputation: 165
In SwiftData lets say we have a long running background Task
. For example on that calculates statistics on all items. Then the user deletes an item (a @Model
instance). How can the Task
handle the deleted model?
struct SomeView: View {
@Environment(\.modelContext) private var context
var body: some View {
// ...
Button("Delete item",
action {
context.delete(item)
try! context.save()
}
)
}
}
func calculateStatistics() {
let actor = DataActor(modelContainer: ModelContainer)
Task.detached {
actor.calculateStatistics()
}
}
...
actor DataActor {
let modelContainer: ModelContainer
init(modelContainer: ModelContainer) {
self.modelContainer = modelContainer
}
func calculateStatistics() {
let context = ModelContext(modelContainer)
let items = try! context.fetch(FetchDescriptor<ItemModel>())
items.calculateSums()
items.calculateStuff()
// ...
// <Here the user deletes an item and we manually save or autosave happens>
// ...
items.calculateAverage()
}
}
I keep getting this error on the task
SwiftData/BackingData.swift:866: Fatal error: This model instance was invalidated because its backing data could no longer be found the store. PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://22627349-2903-424B-80B4-31133FAB3C8A/ItemModel/p2), implementation: SwiftData.PersistentIdentifierImplementation)
I think the issue here is that the underlying model is deleted from storage. But how can I avoid this? Do I need to wrap everything in the same actor to prevent concurrency?
Upvotes: 0
Views: 38