From the WWDC lounge:
WWDC Bot APP 8 days ago @Duncan asked: As I understand it, SwiftData model objects are not thread-safe, just like NSManagedObjects. Are there any additional mechanisms to make managing this easier for us than it was in traditional Core Data? e.g., compiler warnings before passing an object out of its context? 2 replies
WWDC Bot APP 8 days ago @Dave N (Apple) answered: We have provided the ModelActor
protocol & the DefaultModelExecutor
to make SwiftData work with Swift Concurrency. Use your ModelContainer
to initialize a ModelContext
in the initializer for your ModelActor
conforming actor object and use that context to initialize a DefaultModelExecutor.
This will allow you to use that context with async functions on your actor.
So something like this:
actor BackgroundPersistence: ModelActor {
nonisolated public let executor: any ModelExecutor
init(container: ModelContainer) {
let context = ModelContext(container)
executor = DefaultModelExecutor(context: context)
}
func store(data: MyModel) throws {
context.insert(data)
try context.save()
}
func loadAllData() throws -> [MyModel] {
let predicate = #Predicate<MyModel> { data in 1==1 }
let sort = SortDescriptor<MyModel>(\.date)
let descriptor = FetchDescriptor(predicate: predicate, sortBy: [sort])
let result = try context.fetch(descriptor)
return result
}
}
And then use it like this:
@MainActor struct RouteView: View {
@Environment(\.modelContext) private var context: ModelContext
var body: some View {
Button("Save") {
save()
}
}
private func save() {
Task(priority: .userInitiated) {
do {
let persistence = BackgroundPersistence(container: context.container)
try await persistence.store(data: myData)
// Not sure if saving the main context is also needed
try context.save()
} catch {
print(error.localizedDescription)
}
}
}
Inserting and fetching works for me like this.
My only problem is that after terminating the app, all the data is gone. I guess there needs to be some kind of way to tell SwiftData to merge the background context into the main context.