Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Property WrapperでDecodableのデフォルト値を設定 / Providin...
Search
Jierong Li
February 26, 2021
360
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Property WrapperでDecodableのデフォルト値を設定 / Providing Default Value for Decodable Property by Property Wrapper
Jierong Li
February 26, 2021
More Decks by Jierong Li
See All by Jierong Li
一般的な通信でも使える バックグラウンドURLSessionの活用方法 / How to use background URLSession for general network data transfer tasks.
myihsan
0
3k
Multi-Module 101
myihsan
0
360
Hierarchical Structure について / About Hierarchical Structure
myihsan
1
530
What’s New in Accessibility WWDC21
myihsan
1
350
モックフレームワーク比較 / Mocking Framework Comparison
myihsan
0
550
Featured
See All Featured
Code Reviewing Like a Champion
maltzj
528
40k
Making Projects Easy
brettharned
120
6.7k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Un-Boring Meetings
codingconduct
0
330
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Technical Leadership for Architectural Decision Making
baasie
3
420
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
140
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
5.9k
From π to Pie charts
rasagy
0
220
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
Utilizing Notion as your number one productivity tool
mfonobong
4
330
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
Transcript
Property Wrapperͽ Decodable΄ϔϢζϸϕ㮔Ψ戔ਧ 櫏JSONϹφϪЀφ揗͚ͧ
Jierong Liҁ҂ • ໌ୗտᐒΜΗΕ • iOSεЀυϘί • h&ps:/ /jierong.dev •
ڡΗͼ晁㻑ιϐϑϷ݇ے
Ξͥ͘ΡDecodable enum Bar: String, Decodable { case case1, case2 }
struct Foo: Decodable { let array: [Int] let string: String let int: Int let double: Double let bar: Bar }
ϔϢζϸϕ㮔戔ਧ enum Bar: String, Decodable { case case1, case2 }
struct Foo: Decodable { let array: [Int] let string: String let int: Int let double: Double let bar: Bar private enum CodingKeys: CodingKey { case array, string, int, double, bar } init(from decoder: Decoder) throws { let container = decoder.container(keyedBy: CodingKeys.self) array = decoder.decodeIfPresent([Int].self, forKey: .array) ?? [] string = decoder.decodeIfPresent(String.self, forKey: .string) ?? "" int = decoder.decodeIfPresent(Int.self, forKey: .int) ?? 0 double = decoder.decodeIfPresent(Double.self, forKey: .double) ?? -1 bar = decoder.decodeIfPresent(Bar.self, forKey: .bar) ?? .case2 } }
᭗ଉαϘτϰ϶ασЄ enum Bar: String, Decodable { case case1, case2 }
struct Foo: Decodable { let array: [Int] let string: String let int: Int let double: Double let bar: Bar private enum CodingKeys: CodingKey { case array, string, int, double, bar } init(from decoder: Decoder) throws { let container = decoder.container(keyedBy: CodingKeys.self) array = decoder.decodeIfPresent([Int].self, forKey: .array) ?? [] string = decoder.decodeIfPresent(String.self, forKey: .string) ?? "" int = decoder.decodeIfPresent(Int.self, forKey: .int) ?? 0 double = decoder.decodeIfPresent(Double.self, forKey: .double) ?? -1 bar = decoder.decodeIfPresent(Bar.self, forKey: .bar) ?? .case2 } init(array: [Int] = [], string: String = "", int: Int = 0, double: Double = -1, bar: Bar = .case2) { self.array = array self.string = string self.int = int self.double = double self.bar = bar } }
ϔϢζϸϕ㮔͢ӞͺͶͧͽΘ enum Bar: String, Decodable { case case1, case2 }
struct Foo: Decodable { let array: [Int] let string: String let int: Int let double: Double let bar: Bar private enum CodingKeys: CodingKey { case array, string, int, double, bar } init(from decoder: Decoder) throws { let container = decoder.container(keyedBy: CodingKeys.self) array = decoder.decodeIfPresent([Int].self, forKey: .array) ?? [] string = decoder.decode(String.self, forKey: .string) int = decoder.decode(Int.self, forKey: .int) double = decoder.decode(Double.self, forKey: .double) bar = decoder.decode(Bar.self, forKey: .bar) } init(array: [Int] = [], string: String, int: Int, double: Double, bar: Bar) { self.array = array self.string = string self.int = int self.double = double self.bar = bar } }
晄౮ͭ͵͚ͩ; • Property WrapperͽϔϢζϸϕ㮔΄戔ਧ • ݶͮόαϤ䌏ͭͼ晅͜ϔϢζϸϕ㮔΄戔ਧ • όαϤࢴํϔϢζϸϕ㮔΄戔ਧ
ݶͮόαϤ䌏ͭͼ晅͜ϔϢζϸϕ㮔΄戔ਧ struct Foo: Decodable { @DefaultBy([]) var array: [Int] }
Decodable΄ᇙΞͼ !
υδϚϷμφͽ䌏㳌 protocol Default { associatedtype Value static var defaultValue: Value
{ get } } @propertyWrapper struct DefaultDecodable<D: Default>: Decodable where D.Value: Decodable { let wrappedValue: D.Value init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() wrappedValue = try container.decode(D.Value.self) } init() { wrappedValue = D.defaultValue } }
ExtensionͽηЄϝЄϺЄϖ extension KeyedDecodingContainer { func decode<D>(_ type: DefaultDecodable<D>.Type, forKey key:
Key) throws -> DefaultDecodable<D> { try decodeIfPresent(type, forKey: key) ?? .init() } }
ᑮ protocol EmptyInitializable { init() } struct EmptyDefault<Value: EmptyInitializable>: Default
{ static var defaultValue: Value { .init() } } extension Array: EmptyInitializable {} extension String: EmptyInitializable {} struct Foo: Decodable { @DefaultDecodable<EmptyDefault> var array: [Int] @DefaultDecodable<EmptyDefault> var string: String ... }
ෆቘ enum CommonDefault { struct Empty<Value: EmptyInitializable>: Default { static
var defaultValue: Value { .init() } } } enum DefaultBy { typealias Empty<Value: Decodable & EmptyInitializable> = DefaultDecodable<CommonDefault.Empty<Value>> } struct Foo: Decodable { @DefaultBy.Empty var array: [Int] @DefaultBy.Empty var string: String ... }
හ㮔 enum CommonDefault { ... struct ZeroInt: Default { static
var defaultValue: Int {̴.zero̴} } struct OneInt: Default { static var defaultValue: Int { 1 } } struct MinusOneInt: Default { static var defaultValue: Int { -1 } } struct ZeroDouble: Default { static var defaultValue: Double {̴.zero̴} } struct OneDouble: Default { static var defaultValue: Double { 1 } } struct MinusOneDouble: Default { static var defaultValue: Double { -1 } } ... }
හ㮔 enum CommonDefault { ... struct Zero<Value: Numeric>: Default {
static var defaultValue: Value {̴.zero̴} } struct One<Value: Numeric>: Default { static var defaultValue: Value { 1 } } struct MinusOne<Value: Numeric>: Default { static var defaultValue: Value { -1 } } } enum DefaultBy { ... typealias Zero<Value: Decodable & Numeric> = DefaultDecodable<CommonDefault.Zero<Value>> typealias One<Value: Decodable & Numeric> = DefaultDecodable<CommonDefault.One<Value>> typealias MinusOne<Value: Decodable & Numeric> = DefaultDecodable<CommonDefault.MinusOne<Value>> } struct Foo: Decodable { ... @DefaultBy.Zero var int: Int @DefaultBy.MinusOne var double: Double ... }
όαϤࢴํ protocol SelfDefault: Default { static var defaultValue: Self {
get } } extension Bar: SelfDefault { var defaultValue: Bar { .case2 } } enum DefaultBy { ... typealias `Self`<Value: Decodable & SelfDefault> = DefaultDecodable<Value> } ςϣμ϶φͽΘSelf΄ګ夹͢伋͵ͱΡ͵Η̵ࣳവ抷͢ӧݢᚆ
όαϤࢴํ protocol SelfDefault { static var defaultValue: Self { get
} } enum CommonDefault { ... struct `Self`<Value: SelfDefault>: Default { static var defaultValue: Value { Value.defaultValue } } } enum DefaultBy { ... typealias `Self`<Value: Decodable & SelfDefault> = DefaultDecodable<CommonDefault.Self<Value>> } struct Foo: Decodable { ... @DefaultBy.Self var bar: Bar }
๋奰奾ຎ struct Foo: Decodable { @DefaultBy.Empty var array: [Int] @DefaultBy.Empty
var string: String @DefaultBy.Zero var int: Int @DefaultBy.MinusOne var double: Double @DefaultBy.Self var bar: Bar } φϐκϷͭ͵̵ͭ᭗ଉαϘτϰ϶ασЄΘκЄϤ h"ps:/ /github.com/myihsan/DefaultDecodableWrapper
ΚΟͭ͡͵ͩ; extension DefaultDecodable: Equatable where D.Value: Equatable {} extension DefaultDecodable:
Encodable where D.Value: Encodable {}
ΚΟͭ͡͵ͩ; extension DefaultDecodable: Equatable where D.Value: Equatable {} // extension
DefaultDecodable: Encodable where D.Value: Encodable {}̴ // { "wrappedValue": 1 } extension DefaultDecodable: Encodable where D.Value: Encodable { public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(wrappedValue) } } ϓφϕώЄϭ;ץྋͭ͵ϮЀϝЄఽ拽
ͪᶉ宛͘Π͢;͚ͪͬ͜Δͯ