Skip to content

Instantly share code, notes, and snippets.

@0x1306a94
Forked from onevcat/Default.swift
Created July 16, 2021 00:08
Show Gist options
  • Save 0x1306a94/d1089e86dea14bbf90d9556e0d1da6b8 to your computer and use it in GitHub Desktop.
Save 0x1306a94/d1089e86dea14bbf90d9556e0d1da6b8 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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment