Skip to content

Instantly share code, notes, and snippets.

@IanKeen
Last active October 8, 2020 16:46
Show Gist options
  • Select an option

  • Save IanKeen/f569f1e87cbbb55c262536a78c3cd6a4 to your computer and use it in GitHub Desktop.

Select an option

Save IanKeen/f569f1e87cbbb55c262536a78c3cd6a4 to your computer and use it in GitHub Desktop.
Hack Codable support on to @published (don't use this 😅)
extension Published: Decodable where Value: Decodable {
public init(from decoder: Decoder) throws {
try self.init(initialValue: Value(from: decoder))
}
}
extension Published: Encodable where Value: Encodable {
public func encode(to encoder: Encoder) throws {
let mirror = Mirror(reflecting: self)
// The internal structure uses a `Storage` enum
// The case that is used appears to depend on how the instance is being used
func value() -> Value? {
return mirror.descendant("storage", "value") as? Value
}
func publisherValue() -> Value? {
return mirror.descendant("storage", "publisher", "subject", "currentValue") as? Value
}
guard let value = value() ?? publisherValue() else {
throw EncodingError.invalidValue(self, .init(codingPath: encoder.codingPath, debugDescription: "Unable to find value"))
}
try value.encode(to: encoder)
}
}
class State: ObservableObject, Codable {
@Published var foo: Int = 0
@Published var bar: String = "hello world"
}
let state = State()
state.foo = 42
let data = try! JSONEncoder().encode(state)
print(String(data: data, encoding: .utf8)!) // {"foo":42,"bar":"hello world"}
let model = try! JSONDecoder().decode(State.self, from: data)
print(model.foo) // 42
print(model.bar) // hello world
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment