Hi,
Xcode warns me that NSPersistentContainer
, NSManagedObjectContext
, NSPersistentHistoryTransaction
and NSPersistentHistoryToken
are non-Sendable types and therefore cannot cross actor boundaries.
These warnings occur even when I use @preconcurrency import CoreData
(only works with Xcode 14.0 Beta, in Xcode 13.4.1, it says '@preconcurrency' attribute on module 'CoreData' is unused
)
I understand that types in Core Data have yet to be marked as Sendable
when it makes sense.
Although NSPersistentHistoryTransaction,
and NSPersistentHistoryToken
are reference types, they should qualify to be marked as Sendable
in the future since these are immutable types, am I right?
NSPersistentContainer
provides variables and methods like viewContext
and newBackgroundContext()
. It would make sense that this type is thread-safe. However, I'm not sure about it, especially regarding its loadPersistentStores(completionHandler:)
method. Is NSPersistentContainer
(and its subclass NSPersistentCloudKitContainer
) thread-safe and should it be marked as Sendable
in the future?
The case of and NSManagedObjectContext
confuses me the most. Indeed, it has both thread-safe methods like perform(_:)
and thread-unsafe methods like save()
. Still, it should be possible to cross actor boundaries. Would such a "partially thread-safe" type quality to be marked as Sendable
? If not, how can it cross actor boundaries?
The reason I'm asking these questions is that I have a CoreDataStack
type.
It has mutable variables, such as var lastHistoryToken: NSPersistentHistoryToken?
, needs to perform work without blocking the main thread, such as writing the token to a file, has async methods, uses notification observers, and needs to be marked as Sendable
to be used by other controllers running on different actors.
Since this type is related to back-end work, I made it an Actor
. This type exposes the persistent container, and a method to create new background threads.
However, I need to explicitly annotate all methods using await context.perform { ... }
as nonisolated
in this actor. Not doing so causes a data race to be detected at runtime. Is this a bug, and is making a Core Data stack an Actor the proper way to do it or is there a better solution?
Any help would be greatly appreciated.
Thanks.
Xcode Configuration
Xcode 13.4.1, Xcode 14.0 beta 5
The Xcode project is configured with Other Swift Flags set to -Xfrontend -warn-concurrency -Xfrontend -enable-actor-data-race-checks
.