Swift 6.2 Approachable Concurrency & Default Actor Isolation with Core Data Transformable type

I am using Xcode 26.0.1 and Swift 6.2 on my project with the following settings on the target:

Approachable Concurrency: Yes
Default Actor Isolation: MainActor
Strict Concurrency Checking: Complete
Swift Language Version: 6

In my Core Data implementation there is a Transformable type that gets encoded/decoded through NSSecureUnarchiveFromDataTransformer.

Now, due to the aforementioned settings I get the following warnings in my transformer class because the class overrides cannot change the isolation:

Main actor-isolated initializer 'init()' has different actor isolation from nonisolated overridden declaration

Main actor-isolated class method 'allowsReverseTransformation()' has different actor isolation from nonisolated overridden declaration

Main actor-isolated class method 'transformedValueClass()' has different actor isolation from nonisolated overridden declaration

Main actor-isolated class property 'allowedTopLevelClasses' has different actor isolation from nonisolated overridden declaration

@objc(QuizSettingsTransformer)
final class QuizSettingsTransformer: NSSecureUnarchiveFromDataTransformer {
    static let transformerName = NSValueTransformerName(rawValue: String(describing: QuizSettingsTransformer.self))
    
    static func register() {
        let transformer = QuizSettingsTransformer()
        ValueTransformer.setValueTransformer(transformer, forName: transformerName)
    }
    
    override class func allowsReverseTransformation() -> Bool {
        return true
    }
    
    override class func transformedValueClass() -> AnyClass {
        return SerializableQuizSettings.self
    }

    override class var allowedTopLevelClasses: [AnyClass] {
        return [SerializableQuizSettings.self]
    }
}

The overrides are necessary for the Transformable type to work with Core Data. I can silence the warnings by making the QuizSettingsTransformer nonisolated. The project then compiles.

However, that will result in a runtime crash when CloudKit data arrives (which does not come from the main thread) since all other code in the project as well as the SerializableQuizSettings that are used for the decoding/encoding are automatically ran on the @MainActor due to the aforementioned settings.

The fault is dispatch_assert_queue_fail:

Which is expected. When I added a print of the Thread.isMainThread inside the allowedTopLevelClasses var, it would print false just before the app crashes.

The SerializableQuizSettings’s code is:

@objc(SerializableQuizSettings)
public final class SerializableQuizSettings: NSObject, NSSecureCoding {
    public static let supportsSecureCoding = true
    private(set) var quizSettings = QuizSettings.default
    
    private enum CodingKeys: CodingKey {
        case quizSettings
    }
    
    init(quizSettings: QuizSettings) {
        self.quizSettings = quizSettings
        super.init()
    }
    
    public required init?(coder decoder: NSCoder) {
        guard
            decoder.containsValue(forKey: CodingKeys.quizSettings.stringValue),
            let data = decoder.decodeObject(of: NSData.self, forKey: CodingKeys.quizSettings.stringValue) as? Data,
            let quizSettings = try? JSONDecoder().decode(QuizSettings.self, from: data)
        else {
            super.init()
            return
        }
        
        self.quizSettings = quizSettings
        super.init()
    }

    public func encode(with coder: NSCoder) {
        if let data = try? JSONEncoder().encode(quizSettings) {
            coder.encode(data, forKey: CodingKeys.quizSettings.stringValue)
        }
    }
}

I cannot make that nonisolated as well since then the QuizSettings struct then also needs adapting because it is on the @MainActor:

Main actor-isolated conformance of 'QuizSettings' to 'Decodable' cannot be used in nonisolated context

Doing that would further propagate the error through my whole codebase.

I could fix the issue by creating a nonisolated struct QuizSettingsDTO: Codable that simply stores the QuizSettings inside, but that would then loose the user’s data since the data currently being stored in CoreData is of the QuizSettings type.

I am quite stuck at the moment and don’t know how I can go around the limitations in place without turning in circles. Did I miss something? How can I ensure that the QuizSettingsTransformer is also ran on the MainActor with the override class limitations, is that even possible?

Thank you for having a look at this, perhaps someone else has tackled it successfully!