์ง๋ ํธ์ ์ด์ด์ ์งํ!
๋ชฉํ: ์ ํธ ๋ง์ง๋ง์ ์ธ๊ธํ๊ฒ ์ฒ๋ผ Generic์ ์ด์ฉํ์ฌ ๋ฐ๋ณต๋๋ ์ฝ๋๋ฅผ ์ค์ด๊ธฐ
์ด ์๋ฆฌ์ฆ๋ฅผ ์ด์ด๊ฐ๋ฉด์ ํด์จ๊ฒ๋ค์ ์ ๋ฆฌํ๋ฉด ๋จ์ํ๊ฒ๋ ๋ค์๊ณผ ๊ฐ์ด ๋ณผ ์ ์๋ค.
JSON ๊ฐ์ ๊ฐ์ฒดํ ํ ๋ ๋ค์๊ณผ ๊ฐ์ ์ ํ๋ค์ด ์์๋ค.
- ์ต์ ๋ Int -> Int (Default: 0)
- ์ต์ ๋ String -> String (Default: โโ)
- ์ต์ ๋ String -> Bool (Default: false)
(3์ ๊ฒฝ์ฐ๋ { "abc": "Y" }
๊ฐ์ ๊ฐ์ Bool
ํํ๋ก ๋ฐ๊ฟ์ฃผ๋ ๋ค๋ฅธ ํ์
์ฒ๋ฆฌ์๋ค.)
์ด๊ฒ์ ์ด์๊ฒ ๋ฌถ์ด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
์ค๋ฅธ์ชฝ์ ๊ฒฝ์ฐ๋ ๊ฐ ์ฒ๋ฆฌ๋ฐฉ๋ฒ์ด ๋ค๋ฅด๋ฏ๋ก Generic
์ผ๋ก ๋ฌถ๊ธฐ๊ฐ ํ๋ค๊ฒ ์ง๋ง
์ผ์ชฝ์ ๊ฒฝ์ฐ๋ ๊ณตํต์ ์ผ๋ก โํ์ ์ด ๊ฐ๊ณ ๊ธฐ๋ณธ๊ฐ์ ๊ฐ์ง๋ค.โ ๋ผ๋ ์ ์ ์ด์ฉํ์ฌ ๋ฌถ์ด๋ณด๋๋ก ํ์
๊ทธ๋ฆฌ๊ณ ๋ฐฐ์ด๋ JSON ๊ฐ์ผ๋ก ์์ฃผ ๋์ค๋ ์ด๋ ๊ฒ ๋ฌถ์ด๋ณด์.
๊ทธ๋ฆฌ๊ณ ์ต์ข ์ ์ผ๋ก ๋ชจ๋ ๊ฒ์ JSON ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌ ํ๊ธฐ ์ํ ๊ฒ์ด๋ฏ๋ก ๋ถ์ฐ๋์ด์์ผ๋ฉด ๊ด๋ฆฌ๊ฐ ์ด๋ ค์ฐ๋
์ ๋ถ๋ฅผ ๋ฌถ์.
๊ธฐ๋ณธ๊ฐ ์ฒ๋ฆฌ๋ ์ด์ ํธ์ ํ์ผ๋ ์ด๋ฒํธ์ Generic
์ ์ค์ ์ผ๋ก ๋ณด๊ฒ ๋ ๊ฒ์ด๊ณ ,
๋ค๋ฅธ ํ์
์ฒ๋ฆฌ ๋ค์ํธ์์ ์งํ ์์ (์ถ๊ฐ๋ก decodable Array
๋!)
๋จ์ผ์ Property Wrapper๋ฅผ ์ด์ฉํ์ฌ ์ฌ์ฉ์ ๋ถ๊ฐ๋ฅํ๋ค.
์ฌ๊ธฐ์์ ๊ฒฝ์ฐ ์ด๋ฐ์ ๋ฌถ์ ๊ฒ์ฒ๋ผ ๊ฐ์ ๊ธฐ๋ณธํ ์ฒ๋ฆฌ๋ฉํผ, ๋ค๋ฅธ ํ์ ์ฉ ๋ฉํผ๋ ๋ณ๋๋ก ์ด์ฉ๋๋ฉฐ
Enum์ ์ด์ฉํ์ฌ ๋ฌถ์ด์ฃผ๊ฒ ๋๋ค.
Property Wrapper & ๊ธฐ๋ณธ๊ฐ ์ฒ๋ฆฌ ๊ทธ๋ฆฌ๊ณ Generic
Protocol
Generic์ผ๋ก ๋ฌถ๊ธฐ์ ํฌ์ธํธ๋ ํ๋กํ ์ฝ์ ์ด์ฉํ๋ฉฐ ์ด๊ธฐ๊ฐ์ ๋ฐ๋๋ค๋ ์ ์ด๋ค.
protocol DefaultWrapperAvailable {
associatedtype ValueType: Decodable
static var defaultValue: ValueType { get }
}
์์ ์ฝ๋๋ฅผ ๋ณด์.
๊ธฐ๋ณธ๊ฐ ๋ฉํผ๋ฅผ ์ด์ฉํ ์ ์๋ ํ๋กํ ์ฝ์ ๋ง๋ค์๋ค.
associatedtype
๋ผ๋ ๊ฒ์ ํ๋กํ ์ฝ์์ ์ฐ์ผ ์ ์๋๋ฐ,
๋๋์ ์ฝ๊ฐ Generic
๊ณผ ๋น์ทํ๋ค.
์ด ์๋ฆฌ์ ์ด๋ค ํ์ ์ด๋ ์ฌ ์๊ฐ ์๋ค.
ํ๋กํ ์ฝ์ด๋ผ๋ ์์ฒด๊ฐ ์๋ก์ ์์กด์ฑ์ ์ค์ฌ์ฃผ๊ณ ์ ์ฉ์ ํด๋น ๊ท์ฝ? ๊ท์น?๋ค์ ๋ฐ๋ผ์ผ ํ๋ค๋ ๊ฒ์ธ๋ฐ
๊ทธ๋ฌ๋ค๋ณด๋ ๋ฒ์ฉ์ฑ์ด ํ์ํด์ ๋ง๋ค์ด์ง๊ฒ ์๋๊ฐ ์ถ๋ค. (๊ฐ์ธ์ ์๊ฐ)
๋๋ฒ์งธ ์ค์ ๋ณด๊ณ ๋์ ์ข๋ ์ค๋ช ์ ํด์ผ ์ดํดํ๊ธฐ๊ฐ ์ฌ์ธ๋ฏ ํ๋ค.
static var
๋ก ์ ์ธ์ ํด์ค ํ๋กํผํฐ์ ํ์
์ ๋ณด๋ฉด ValueType
์ด๋ค.
์ ๋ฐ ํ์
์ ์ค์ ์์ง๋ง ๊ทธ ์์ค์ associatedtype
๋ก ์ ์ด์ฃผ์๊ณ , ๊ทธ ํ์
์ด๋ผ๋ ์๋ฏธ๋ค.
๊ทธ๋์ ํด๋น ํ๋กํ ์ฝ์ ์ ์ฉ์ํค๊ฒ ๋๋ค๋ฉด ๋ฐ๋์ ValueType
์ด๋ ์ด๋ค ํ์
์ธ๊ฐ๋ฅผ ๋ช
์๋ฅผ ํด์ค์ผํ๋ค.
ํ์ง๋ง, ์กฐ๊ฑด์ด ํ๋ ๋ ๋ถ์ด์๋ค. ์ด ํ์
์ Decodable
์ ๋ฐ๋ผ์ผ ํ๋ค๋ ์ ์ด๋ค.
associatedtype
๋ ์ด์ ๋๋ก๋ง ์ค๋ช
์ ํ๊ณ ,
์ ํ๋์ง๊ฐ ์ค์ํ๋ค.
ํต์ ํ Decodable
์ ์ด์ฉํ์ฌ
๋ค์ํ ์๋ฃํ์ ๊ธฐ๋ณธ๊ฐ์ ์ฒ๋ฆฌํ๋ ๋ถ๋ถ์ด๊ธฐ ๋๋ฌธ์
associatedtype
์ด ํ์ํ๊ณ , ์ด ์๋ฃํ๋ค์ Decodable
์ ๋ฐ๋ผ์ผํ๋ค.
๊ทธ๋ฆฌ๊ณ ๊ธฐ๋ณธ๊ฐ์ ๋จ์ํ ํด๋น ํ๋กํ ์ฝ์ ๋ฐ๋ฅด๋ ๊ฐ์ฒด์์
๊ธฐ๋ณธ๊ฐ์ด ๋ฌด์์ธ์ง๋ง ํ์ํ๋ฏ๋ก ํ์
ํ๋กํผํฐ(static var)
๋ก์จ get
๋ง ํ์ํ๋ค.
์ด๊ธฐํ๋ ๋ถํ์ํ๋ค.
์ด ๊ธ์์ ์ด๊ธฐํ๊ฐ ๋ถํ์ํ๋ค๋ ๋ง์ด ์์ฃผ ๋์จ๋ค.
Property Wrapper ์ ์ธ
@propertyWrapper
struct Wrapper<T: JSONDefaultWrapperAvailable> {
typealias ValueType = T.ValueType
var wrappedValue: ValueType
init() {
wrappedValue = T.defaultValue
}
}
๋ฉํผ ์์ฑ ๋ถ๋ถ์ด๋ค.
์ด์ ๊ณผ ๋ค๋ฅธ ๋ถ๋ถ์ <T: JSONDefaultWrapperAvailable>
์ด ๊ฐ์ฅ ๋จผ์ ๋์ ๋ค์ด์ค๊ฒ ๋ ํ
๋ฐ,
Generic T
๋ผ๋ ๊ฐ์ ์ ์ธ์ ์ ์ ํด์ค์ผํ๋ฉฐ, ์ด๋ ์์์ ๋ง๋ ํ๋กํ ์ฝ
์ ๋ฐ๋ฅด๊ฒ ๋๋ค.
associatedtype
์๋ ๋ถ๋ถ์ typealias
๋ฅผ ์ด์ฉํ์ฌ ์ ์๋ฅผ ํด์ฃผ๊ณ , ๊ธฐ๋ณธ ๊ฐ
๋ํ ์ ์ ์๋ค.
์ฆ, ์ฐ๋ฆฌ๋ ๊ธฐ๋ณธ๊ฐ์ ๋ฏธ๋ฆฌ ๋ฐ์์ฌ ์ ์๊ณ ,
๊ทธ ๋ฐ์์จ ๊ฐ์ init
์ ํธ์ถํ ๋ ๋ฃ๊ฒ ๋ค๋ ๊ฒ์ด๋ค.
์ฌ๊ธฐ์ ํต์ฌ์ด ์ ๋ถ๋ถ์ด๋ค.
decode
ํ๊ฒ๋๋ฉด try
๋ฅผ ํ๊ฒ ๋ ํ
๊ณ , JSON
์ ํด๋น ํค๊ฐ ์์ ๊ฒฝ์ฐ ์ด๋ ๋ฑ์ด์ง๊ฒ ๋๋๋ฐ,
์ด๋ init
์ ํ๊ฒ ๋๊ณ , ๊ทธ ๋์ ๊ฐ์ด ์ defaultValue
๋ฅผ ์ด์ฉํ์ฌ init
์ ํด์ค์ผ๋ก์จ
ํค๊ฐ ์์ด๋ ๊ธฐ๋ณธ๊ฐ์ ์ ์ํ ์ ์๊ฒ ๋๋ค.
Protocol๊ณผ Enum
์์ ๋ง๋ ํ๋กํ ์ฝ์ ๋ฐ๋ฅด๋ ๋ฌด์ธ๊ฐ๊ฐ ํ์ํ๋ค.
๊ทธ๋์ผ ๊ฐ ์๋ฃํ ๋ณ ๊ธฐ๋ณธ๊ฐ์ ๋ฃ์ด์ฃผ๊ฒ ๋ ํ ๋๊น!
๊ทธ๋ ๋ด ๋ณดํต์ ํ๋กํ ์ฝ์ ์ ์ฉ์ํฌ๋ class
,struct
๋๊ฐ์ง์ ์ ์ฉ์ ๋ง์ด ํ๊ฒ ๋ ํ
๋ฐ,
๋๊ฐ์ง์ ๊ณตํต์ ์ด ์๋ค.
ํ๋กํผํฐ์ ๋ฉ์๋๊ฐ ์๋๋ผ๋ ์ด๊ธฐํ๊ฐ ๋๋ค
๋ค์์ ๋ณด์
// 1. ์์ฑ
class AA {
}
struct BB {
}
// ์ด๋๊ฐ..
// 2. ์ ์ธ ๋ฐ ์ด๊ธฐํ
let aa = AA()
let bb = BB()
ํด๋์ค AA์ ๊ตฌ์กฐ์ฒด BB๋ฅผ ๋ง๋ค์ด ์ฃผ์๊ณ ์ฃผ์2์ ๊ฐ์ด ์ ์ธ๊ณผ ์ด๊ธฐํ๋ฅผ ํด์ฃผ์๋ค.
ํ๋กํผํฐ์ ๋ฉ์๋๊ฐ ์์์๋.
๋ค์ ์ฐ๋ฆฌ๊ฐ ๋ง๋ ํ๋กํ ์ฝ์ ๋ณด์.
protocol JSONDefaultWrapperAvailable {
associatedtype ValueType: Decodable
static var defaultValue: ValueType { get }
}
์ฌ๊ธฐ์ ์ด ํ๋กํ ์ฝ์ ๋ฐ๋ฅด๋ ๊ฒ์ ์ด๊ธฐํ ๋ ํ์์ฑ์ด ์๋๊ฐ?
์๋๋ค ์ ํ ํ์์๋ค.
๋จ์ํ๊ฒ
- ์๋ฃํ์ ๋ฌด์์ธ๊ฐ?
- ์ด ์๋ฃํ์ ๊ฐ์ง ๊ธฐ๋ณธ๊ฐ์ ๋ฌด์์ธ๊ฐ?
์ด ๋๊ฐ์ง ์ ์๋ง ํ์ํ ๋ฟ ์ด๊ธฐํ๋ ์ด์ ๋ ์ ํ ์๋ค.
๊ทธ๋์ Enum
์ด ๋์ค๊ฒ ๋๋ค.
์ด๊ฑฐํ์๋ ํ๋กํ ์ฝ์ ์ ์ฉ์ํฌ ์ ์๋ค. ๊ทธ์น๋ง ๋ค๋ฅธ์ ์ ์์ ๊ฐ์ด ์ด๊ธฐํ๊ฐ ์๋๋ค๋ ๊ฒ์ด๋ค.
์์ ์ค์ท์ ๋ณด๋ฉด ๋๊ฐ์ง ์ด๊ฑฐํ์ด ์๋ค.
CC
: ํ๋กํผํฐ, ๋ฉ์๋ ์ ์ xDD
: ํ๋กํผํฐ, ๋ฉ์๋ ์ ์ x, ํ๋กํ ์ฝ o
DD
์ ๋ด์ฉ๋ฌผ์ ์กฐ๊ธ ๋ค์ ์๊ธฐํ๊ณ , ์ด๋ฏธ์ง ์๋ ๋ถ๋ถ ์๋ฌ๋ฅผ ๋ณด๋ฉด
์ด๊ธฐํ๋ฅผ ํ ์ ์๋ค๋๊ฒ์ด ์ค์ ์ด๋ค. ๋ถํ์ํ ์ด๊ธฐํ๋ ์ ์ด์ ์ฐจ๋จ!
๊ทธ๋ ๊ธฐ์ ์ฌ๊ธฐ์ class
,struct
๊ฐ ์๋ enum
์ ํ๋กํ ์ฝ์ ์ ์ฉ ํ ๊ฒ์ด๋ค.
Enum ์ ์
์ฌ๊ธฐ์๋ถํฐ๋ ๊ฐ ์๋ฃํ๋ณ๋ก Enum
์ ํ๋กํ ์ฝ์ ์ ์ฉํ์ฌ ์ ์ํด๋ณด์
์ฐ์ Bool
๊ณผ String
๋ถํฐ!
enum True: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - true
static var defaultValue: Bool { true }
}
enum False: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - false
static var defaultValue: Bool { false }
}
enum EmptyString: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - ""
static var defaultValue: String { "" }
}
์์ ์๋ฌ ์ด๋ฏธ์ง ์บก์ณ๋ณธ๊ณผ ์ฐจ์ด๊ฐ ์๋ค๋ฉด(enum DD
), typealias
๊ฐ ์๋ค๋์ ์ด๋ค.
์ถ๋ก ์ด ๋ ์ํฉ์ธ๋ฐ, ํ๋กํ ์ฝ ์ ์๋ถ๋ฅผ ๋ณด๋ฉด defaultValue
ํ์
์ด ValueType
์ด์๋๋ฐ,
์ด๋ฅผ ์ด์ฉํ์ฌ defaultValue
์ ํ์
์ ์ ์ํ๋ฉด typealias
๋ ๋ณ๋๋ก ์ ์ํ ํ์๊ฐ ์๋ค.
์์ ๋ด์ฉ์ ๊ฐ๋จํ๋ค. ๊ธฐ๋ณธ๊ฐ ํ๋กํ ์ฝ์ ๋ฐ๋ฅธ๋ค๋ ๊ฒ๊ณผ ๊ทธ๋ฆฌ๊ณ ๊ธฐ๋ณธ๊ฐ์ ๊ฐ๊ฐ ์ง์ ํด์คฌ๋ค๋ ์ ์ด๋ค.
JSON
๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ถ๋ถ์ ๋ถ์ฐ์ ๋ง๊ธฐ์ํด property wrapper
์ enum
๋ค์ ๋ค์ ํ๋ฒ
enum
์ผ๋ก ๋ฌถ์
enum
์ผ๋ก ๋ฌถ๋ ์ด์ ๋ ๋ค์ ํ๋ฒ ๋งํ๋ฉด, ๋ถํ์ํ ์ด๊ธฐํ๋ฅผ ๋ฐฉ์ง ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ด๋ค.
์ด๋ ๊ฒ.
enum JSONDefaultWrapper {
// Property Wrapper
@propertyWrapper
struct Wrapper<T: JSONDefaultWrapperAvailable> {
typealias ValueType = T.ValueType
var wrappedValue: ValueType
init() {
wrappedValue = T.defaultValue
}
}
// Type Enums
enum True: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - true
static var defaultValue: Bool { true }
}
enum False: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - false
static var defaultValue: Bool { false }
}
enum EmptyString: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - ""
static var defaultValue: String { "" }
}
}
๊ทธ๋ฆฌ๊ณ ์ด์ ํธ์ ๋์จ ๊ฒ๋ค์ ๋์๊ฒจ๋ณด๋ฉด,
- ๋ฉํผ์
init(from decoder: Decoder)
์ ์๊ฐ ํ์ํ๋ค
extension JSONDefaultWrapper.Wrapper: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.wrappedValue = try container.decode(ValueType.self)
}
}
KeyedDecodingContainer
์extension
ํ์ฌdecode
๋ฉ์๋ ์ถ๊ฐ ํ์ํ๋ค.
extension KeyedDecodingContainer {
func decode<T: JSONDefaultWrapperAvailable>(_ type: JSONDefaultWrapper.Wrapper<T>.Type, forKey key: Key) throws -> JSONDefaultWrapper.Wrapper<T> {
try decodeIfPresent(type, forKey: key) ?? .init()
}
}
์์ ๊ฐ์ด ์ ํ ์ ํด์ฃผ๋ฉด ์ฌ์ฉํ ์ค๋น๋ ๋๋ฌ๋ค.
์ค์ ์ ์ฉ ์ฝ๋์ ์ถ๋ ฅ ๊ฐ์ด๋ค.
์ ์ด๋ฏธ์ง๋ฅผ ์ค๋ช ํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
- ๋งจ ์ฒซ์ค์
stringValue
๋ ์ต์ ๋์ด ์๋String
์ด๋ค. JSON
ํํ์ ๋ฐ์ดํฐ๋stringValue
์ ๊ด๋ จ๋ ํค๊ฐ ์๋ค. (์ด๋ฌํ ์ด์ ๋๋ฌธ์ ๋ณ๋ ์ฒ๋ฆฌ๊ฐ ์์๋ค๋ฉด error๋ฅผ ๋ฑ๊ฒ ๋๋ค.)Decode
๋ฅผ ํ์๋,stringValue
๊ฐ ๋น๊ฐ์ธ์ง ํ์ธ์ด ๋์๋ค.
2๊ฐ ํต์ฌ์ด๋ค. ๊ด๋ จ ํค๊ฐ ์์ง๋ง ๊ฐ์ฒด๊ฐ ์ ์์ฑ ๋์๋ค.
๊ทธ๋ผ ์์ enum
์ ์ ๋ถ ์ ์ฉํ์ฌ ๋ค์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์.
์์ฃผ ์์ฃผ ์ ๋์๋ค!
์ด์ JSON
๋ฐ์ดํฐ์ ํด๋น ํค๊ฐ ์์ด๋ ๋ฌธ์ ์๋ค!
๊ทธ์น๋ง ๋ชป์๊ธด๊ฑด ๋ฌธ์ ๊ฐ ์๋ค.
@JSONDefaultWrapper.Wrapper<JSONDefaultWrapper.EmptyString> var stringValue: String
@JSONDefaultWrapper.Wrapper<JSONDefaultWrapper.True> var trueValue: Bool
@JSONDefaultWrapper.Wrapper<JSONDefaultWrapper.False> var falseValue: Bool
์ ์ด ์ผ๋ง๋ ํด๊ดดํ๊ฒ ์๊ฒผ๋๊ฐ;;
๊ต์ฅํ ๋์ฐํ๊ณ ๊ฐ๋ ์ฑ๋ ๋ณ๋ก ๊ทธ๋ฅ ๋ณ๋ก๋ค.
typealias
๋ฅผ ํตํด ์ ๋ฆฌ์ข ํด์ฃผ์.
์ ๋ฆฌํ๊ธฐ ์์ ์๋ enum
๋ค์ JSONDefaultWrapper
๋ฅผ ์น๊ณ
.
์ ๋๋ฅด๋ฉด ์๋์์ฑ์ด ์ดค๋ผ๋ฝ ๋จ๊ฒ ๋ ํ
๋ฐ,
์ด ๋ถ๋ถ์ ์ ๋ฆฌ ํ ๊ฒ์ด๋ ์๋์์ฑ์ ํ์ถ๋๊ธธ ์์น ์๋๋ค.
์ด๊ฒ๋ค ๋ํ ๋ค์ ํ๋ฒ enum
์ผ๋ก ๋ฌถ์ด์ฃผ์
enum TypeCase {
// Type Enums
enum True: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - true
static var defaultValue: Bool { true }
}
enum False: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - false
static var defaultValue: Bool { false }
}
enum EmptyString: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - ""
static var defaultValue: String { "" }
}
}
์ด๋ ๊ฒ ๋ง์ด๋ค.
๊ทธ๋ฆฌ๊ณ ๋์ ์๊น ๋ชป์๊ธด ๋ถ๋ถ๋ค์ typealias
๋ก ๋ค์ ์ ์ด์ฃผ์
enum JSONDefaultWrapper {
typealias EmptyString = Wrapper<JSONDefaultWrapper.TypeCase.EmptyString>
typealias True = Wrapper<JSONDefaultWrapper.TypeCase.True>
typealias False = Wrapper<JSONDefaultWrapper.TypeCase.False>
// ...
}
๊ทธ๋ผ ๋ค์ ์ฌ์ฉํ๋ ๋ถ๋ถ์ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ ๋ฆฌ๊ฐ ๋๋ค.
@JSONDefaultWrapper.EmptyString var stringValue: String
@JSONDefaultWrapper.True var trueValue: Bool
@JSONDefaultWrapper.False var falseValue: Bool
์ค ํจ์ฌ ๊น๋ํ๋ค!
๊ทธ๋ผ ์ด์ ์ฌ์ฉ๋ฒ์ ์์์ผ๋ ์ซ์๋ค์ ๋ํด์๋ ํด๋ณด์.
์ซ์ ์ฒ๋ฆฌ
์ผ๋ถ๋ก ์ซ์ ์๋ฃํ๋ค์ ๋ฐ๋ก ๋บ๋๋ฐ
Int
, Double
, Float
, CGFloat
๋ฑ๋ฑ ์ซ์ ๊ด๋ จ ์๋ฃํ์ด ๋ง๋ค.
๊ทธ๋ ๋จ ๋ง์ enum TypeCase
์์ ๊ฐ ์๋ฃํ๋ณ enum
์ด ์ถ๊ฐ ๋์ด์ผ ํ๋ค๋ ๊ฒ์ธ๋ฐ
์ด๊ฒ์ Generic
์ผ๋ก ๋นผ๋ฒ๋ฆฌ์
์์ฑ๋ณธ์ ๋ค์๊ณผ ๊ฐ๋ค
enum TypeCase {
// Type Enums
enum True: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - true
static var defaultValue: Bool { true }
}
enum False: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - false
static var defaultValue: Bool { false }
}
enum EmptyString: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - ""
static var defaultValue: String { "" }
}
enum Zero<T: Decodable>: JSONDefaultWrapperAvailable where T: Numeric {
// ๊ธฐ๋ณธ๊ฐ - 0
static var defaultValue: T { 0 }
}
}
์ ์ผ ์๋์ Zero
๋ผ๊ณ ์ถ๊ฐํด์คฌ๋๋ฐ Generic T
๊ฐ decodeble
์ ๋ฐ๋ฅด๋ฉฐ, Numeric
๋ํ ๋ฐ๋ฅด๊ฒ ๋๋ค.
์ฌ๊ธฐ์ ํฌ์ธํธ๋ Numeric
์ด๋ผ๋ ์ !
์ซ์ ๊ด๋ จ ์ฒ๋ฆฌ๋ฅผ ๋ค ํด๋ฒ๋ฆด ์ ์๋ค.
ํ์ง๋ง typealias
๋ ์ ์ ํด์ค์ผ์ง ใ
์ฐจ๋ง ์ด๊ฑฐ๊น์ง ๋ชป ์ค์๋ค.
typealias IntZero = Wrapper<JSONDefaultWrapper.TypeCase.Zero<Int>>
typealias DoubleZero = Wrapper<JSONDefaultWrapper.TypeCase.Zero<Double>>
typealias FloatZero = Wrapper<JSONDefaultWrapper.TypeCase.Zero<Float>>
typealias CGFloatZero = Wrapper<JSONDefaultWrapper.TypeCase.Zero<CGFloat>>
์ ๊ทธ๋ผ ๋ค์ ์คํํ์ฌ ์ถ๋ ฅ๊ฐ์ ๋ณด์
ํฌํ.. ๋๋ค..
์ฐ๋ฉด์๋ ๋๋ฌด๋ ํท๊ฐ๋ ธ๋ ์ด๋ฒ ํฌ์คํ
๋๋์ฒด ๋ช๋ฒ์ ์ผ๋ค ์ง์ ๋ค ํ์ง ๋ชจ๋ฅด๊ฒ ๋ค?
๋๋์ด ๋ค์ ํฌ์คํ ์ด ์ด ์๋ฆฌ์ฆ์ ๋ง์ง๋ง์ผ๋ฏ ํ๋ค.
์ด ๊ธ์์ ์ ์๋ JSONDefaultWrapper
์ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๊ณ ๋ง๋ฌด๋ฆฌํ๊ธฐ.
protocol JSONDefaultWrapperAvailable {
associatedtype ValueType: Decodable
static var defaultValue: ValueType { get }
}
enum JSONDefaultWrapper {
typealias EmptyString = Wrapper<JSONDefaultWrapper.TypeCase.EmptyString>
typealias True = Wrapper<JSONDefaultWrapper.TypeCase.True>
typealias False = Wrapper<JSONDefaultWrapper.TypeCase.False>
typealias IntZero = Wrapper<JSONDefaultWrapper.TypeCase.Zero<Int>>
typealias DoubleZero = Wrapper<JSONDefaultWrapper.TypeCase.Zero<Double>>
typealias FloatZero = Wrapper<JSONDefaultWrapper.TypeCase.Zero<Float>>
typealias CGFloatZero = Wrapper<JSONDefaultWrapper.TypeCase.Zero<CGFloat>>
// Property Wrapper
@propertyWrapper
struct Wrapper<T: JSONDefaultWrapperAvailable> {
typealias ValueType = T.ValueType
var wrappedValue: ValueType
init() {
wrappedValue = T.defaultValue
}
}
enum TypeCase {
// Type Enums
enum True: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - true
static var defaultValue: Bool { true }
}
enum False: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - false
static var defaultValue: Bool { false }
}
enum EmptyString: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - ""
static var defaultValue: String { "" }
}
enum Zero<T: Decodable>: JSONDefaultWrapperAvailable where T: Numeric {
// ๊ธฐ๋ณธ๊ฐ - 0
static var defaultValue: T { 0 }
}
}
}
extension JSONDefaultWrapper.Wrapper: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.wrappedValue = try container.decode(ValueType.self)
}
}
extension KeyedDecodingContainer {
func decode<T: JSONDefaultWrapperAvailable>(_ type: JSONDefaultWrapper.Wrapper<T>.Type, forKey key: Key) throws -> JSONDefaultWrapper.Wrapper<T> {
try decodeIfPresent(type, forKey: key) ?? .init()
}
}
๋.