defaultIsolation MainActor and Core Data background tasks

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 new MainActor default isolation feature. These changes include marking NSManagedObject as NS_SWIFT_NONISOLATED NS_SWIFT_NONSENDABLE, marking NSManagedObjectContext as NS_SWIFT_NONISOLATED NS_SWIFT_SENDABLE, and requiring NS_SWIFT_SENDABLE closures for the family of perform, 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 made Sendable. They are expected to be isolated to the scope of the NSManagedObjectContext 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 on NSManagedObjectContext from other threads, it is permissible to pass references around to invoke the performBlock family of methods, for the purpose of routing a Sendable 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 a nonisolated(unsafe) closure local to errors involving MainActor isolated state captured by a performBlock closure:

nonisolated(unsafe) let perform = {
                 // work
             }
             
             try context.performAndWait {
               try perform()
             }
2 Likes