Looks like iOS 26 & companions address this with beta 5:
In beta 5 SDK, CoreData changed several
Sendable
annotations to resolve compatibility issues with Swift 6’s newMainActor
default isolation feature. These changes include markingNSManagedObject
asNS_SWIFT_NONISOLATED NS_SWIFT_NONSENDABLE
, markingNSManagedObjectContext
asNS_SWIFT_NONISOLATED NS_SWIFT_SENDABLE
, and requiringNS_SWIFT_SENDABLE
closures for the family ofperform
,performBlock
,performBlockAndWait
and similar methods. These changes are ABI compatible with past releases but might introduce new warnings while building source code that violates the longstanding CoreData concurrency guidelines.
NSManagedObject
are mutable reference types inextricably related to others in a graph and cannot be madeSendable
. They are expected to be isolated to the scope of theNSManagedObjectContext
that creates or fetches them.NSManagedObjectContext
is a style of actor which encapsulates its own dispatch queue. While it’s impermissible to use many methods onNSManagedObjectContext
from other threads, it is permissible to pass references around to invoke theperformBlock
family of methods, for the purpose of routing aSendable
closure to its managed dispatch queue. CoreData supports a user default-com.apple.CoreData.ConcurrencyDebug 1
which can be used to enable additional assertions. (153848710) (FB18216198)Workaround: Most new warnings detected by Swift from these changes are real data races, although some errors are not properly downgraded to warnings as the
@preconcurrency
attribute would indicate. To work around this, apply anonisolated(unsafe)
closure local to errors involvingMainActor
isolated state captured by aperformBlock
closure:
nonisolated(unsafe) let perform = {
// work
}
try context.performAndWait {
try perform()
}