Skip to content

Instantly share code, notes, and snippets.

@onevcat
Created November 10, 2020 03:56
Show Gist options
  • Save onevcat/0f055ece50bd0c07e882890129dfcfb8 to your computer and use it in GitHub Desktop.
Save onevcat/0f055ece50bd0c07e882890129dfcfb8 to your computer and use it in GitHub Desktop.
Sample code of using Default to decode a property to the default value
import UIKit
protocol DefaultValue {
associatedtype Value: Decodable
static var defaultValue: Value { get }
}
@propertyWrapper
struct Default<T: DefaultValue> {
var wrappedValue: T.Value
}
extension Default: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
wrappedValue = (try? container.decode(T.Value.self)) ?? T.defaultValue
}
}
extension KeyedDecodingContainer {
func decode<T>(
_ type: Default<T>.Type,
forKey key: Key
) throws -> Default<T> where T: DefaultValue {
try decodeIfPresent(type, forKey: key) ?? Default(wrappedValue: T.defaultValue)
}
}
struct Video: Decodable {
enum State: String, Decodable, DefaultValue {
case streaming
case archived
case unknown
static let defaultValue = Video.State.unknown
}
let id: Int
let title: String
@Default.False var commentEnabled: Bool
@Default.True var publicVideo: Bool
@Default<State> var state: State
}
extension Bool {
enum False: DefaultValue {
static let defaultValue = false
}
enum True: DefaultValue {
static let defaultValue = true
}
}
extension Default {
typealias True = Default<Bool.True>
typealias False = Default<Bool.False>
}
let json = #"{"id": 12345, "title": "My First Video", "state": "reserved"}"#
let value = try! JSONDecoder().decode(Video.self, from: json.data(using: .utf8)!)
print(value)
@skywalkerlw
Copy link

can we support default Empty Array and Dictionary?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment