API Response
에서 action
값의 유무에 따라 다른 행동을 해야한다면 init(from decoder: any Decoder) throws
가 아닌 Mirror
를 통해 쉽게 해결할 수 있다.
1
2
3
4
5
| {
“action1”: “some action1”,
“action2”: “some action2”,
“action3”: “some action3”
}
|
1
2
3
4
5
| struct Response: Decodable {
let action1: String?
let action2: String?
let action3: String?
}
|
1
2
3
| let decoded = JSONDecoder().decode(Response.self, from: responseData)
let mirror = Mirror(reflection: decoded)
let doAction = mirror.children.compactMap { $0.value }.first
|
기타
reflection API
는 Swift
와 C++
로 구현되어있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| internal init(internalReflecting subject: Any,
subjectType: Any.Type? = nil,
customAncestor: Mirror? = nil)
{
let subjectType = subjectType ?? _getNormalizedType(subject, type: type(of: subject))
let childCount = _getChildCount(subject, type: subjectType)
let children = (0 ..< childCount).lazy.map({
getChild(of: subject, type: subjectType, index: $0)
})
self.children = Children(children)
self._makeSuperclassMirror = {
guard let subjectClass = subjectType as? AnyClass,
let superclass = _getSuperclass(subjectClass) else {
return nil
}
// Handle custom ancestors. If we've hit the custom ancestor's subject type,
// or descendants are suppressed, return it. Otherwise continue reflecting.
if let customAncestor = customAncestor {
if superclass == customAncestor.subjectType {
return customAncestor
}
if customAncestor._defaultDescendantRepresentation == .suppressed {
return customAncestor
}
}
return Mirror(internalReflecting: subject,
subjectType: superclass,
customAncestor: customAncestor)
}
|
참고
How Mirror Works
Mirror Source
Mirror