Composition of `Codable` and `Observable`

Hello - I noticed that if I mark a Codable class as @Observable, the compiler gives a warning inside the generated code.

@Observable
final class User: Codable {
    let id: Int
    let name: String
}

which expands to...

@Observable
final class User: Codable {
    let id: Int
    let name: String

    /* generated */

    @ObservationIgnored private let _$observationRegistrar = Observation.ObservationRegistrar() // ⚠️ Immutable property will not be decoded because it is declared with an initial value which cannot be overwritten
    
    internal nonisolated func access<Member>(
        keyPath: KeyPath<User, Member>
    ) {
      _$observationRegistrar.access(self, keyPath: keyPath)
    }
    
    internal nonisolated func withMutation<Member, MutationResult>(
      keyPath: KeyPath<User, Member>,
      _ mutation: () throws -> MutationResult
    ) rethrows -> MutationResult {
      try _$observationRegistrar.withMutation(of: self, keyPath: keyPath, mutation)
    }

    /* end generated */
}

Is there any workaround here or are objects marked as @Observable not intended to work with the generated Codable conformance? A custom implementation of encode / init(from decoder:) fixes the warning.

4 Likes

I have the same situation, did you find any update to this?

1 Like

Unfortunately no - it doesn't seem like it's possible to fix this warning.

I see, as it turns out, I found a workaround that at least doesn't require full on custom codable compliance. You can just manually set the coding keys and it will make the compiler happy.

e.g. if you have a var name: String you would set the CodingKeys enum case _name = "name"

And credit is due here, I found this with the details How to Make Codable Work with Swift's New Observation Framework and the @Observable Macro in SwiftUI | Callista

3 Likes