Philip Pegden
Philip Pegden

Reputation: 2164

Conforming @MainActor class, or actor, to Codable

How does one add Codable conformance to a class that needs to be isolated to the MainActor?

For example, the following code gives compiler errors:

@MainActor final class MyClass: Codable {
    var value: Int
    
    enum CodingKeys: String, CodingKey {
        case value
    }
    
    init(from decoder: Decoder) throws { // <-- Compiler error: Initializer 'init(from:)' isolated to global actor 'MainActor' can not satisfy corresponding requirement from protocol 'Decodable'
        let data = try decoder.container(keyedBy: CodingKeys.self)
        self.value = try data.decode(Int.self, forKey: .value)
    }
    
    func encode(to encoder: Encoder) throws { // <-- Compiler error: Instance method 'encode(to:)' isolated to global actor 'MainActor' can not satisfy corresponding requirement from protocol 'Encodable'
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(value, forKey: .value)
    }
}

I'm definitely struggling to get my head around actors and @MainActor at the moment!

Upvotes: 6

Views: 1317

Answers (1)

matt
matt

Reputation: 536028

There isn't anything about the class you've provided that needs to be isolated to the main actor, so don't isolate the class as a whole. If there are other members that you have not shown us that do need to be isolated to the main actor, isolate them.

Example:

final class MyClass: Codable {
    private var value: Int
    @MainActor init(value: Int) {
        self.value = value
    }
    @MainActor func setMyValue(to newValue:Int) {
        self.value = newValue
    }
    @MainActor func getMyValue() -> Int {
        self.value
    }
    enum CodingKeys: String, CodingKey {
        case value
    }
    init(from decoder: Decoder) throws {
        let data = try decoder.container(keyedBy: CodingKeys.self)
        self.value = try data.decode(Int.self, forKey: .value)
    }
    func encode(to encoder: Encoder) throws { // <-- Compiler error: Instance method 'encode(to:)' isolated to global actor 'MainActor' can not satisfy corresponding requirement from protocol 'Encodable'
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(value, forKey: .value)
    }
}

Upvotes: 2

Related Questions