Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- swiftdocs
- RIBs Tutorial
- UICoordinateSpace
- windowScene
- Ribs
- ios
- 대머리깃허브
- 메모리 접근 충돌
- App Signing
- Automatically manage signing
- 로버트마틴형
- Apple Certificate
- Git Large File Storage
- Github file size
- SWIFT
- RxSwift
- 클린아키텍쳐
- conflicting access to memory
- memory safety
- 잡초가득블로그
- Large File Storage
- in-out
- iOS Target
- Concurrent
- rib
- RxCocoa
- iOS 버전 점유율
- Dependency Rule
- Dispatch.main.sync
- coordinateSpace
Archives
- Today
- Total
빙수왕의 개발일지
Decoder 3가지 메소드 정리 (Container 종류) 본문
Decoder의 메소드들 (Container 3가지)
- func container
(keyedBy: Key.Type) throws -> KeyedDecodingContainer - func singleValueContainer() throws -> SingleValueDecodingContainer
- func unkeyedContainer() throws -> UnkeyedDecodingContainer
1. KeyedDecodingContainer
- CodingKey로 넘긴 키타입에 맞는 키를 가지는 값들을 포함하는 컨테이너.
- 일반적인 key: value 형태의 json을 디코딩할 때 사용.
- 우리가 일반적으로 property를 몇개 가진 struct에 Decodable을 준수시키면 init에서 이 형태의 Container가 사용된다.
예시
https://api.sampleapis.com/coffee/hot
위 API 아웃풋인 json을 디코딩한다고 가정하자.
struct Coffee: Decodable {
let title: String?
let description: String
let ingredients: [String]
let image: String
let id: Int
enum CodingKeys: CodingKey {
case title
case description
case ingredients
case image
case id
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.title = try container.decodeIfPresent(String.self, forKey: .title)
self.description = try container.decode(String.self, forKey: .description)
self.ingredients = try container.decode([String].self, forKey: .ingredients)
self.image = try container.decode(String.self, forKey: .image)
self.id = try container.decode(Int.self, forKey: .id)
}
}
2. SingleValueDecodingContainer
- a single primitive value 을 가지는 Container.
- key, value 없이, 값 1개(통으로) 때만 사용하는 아이
- 값 1개라는건 예를들어 String 1개도 되겠지만, 1개의 array도 된다.
예시1
가장 상위의 껍질 struct가 불필요할 때 통 container를 만들어서 내부를 decode하면 좋을 것 같다.
ex) 1개의 array가 들어있는 struct
struct ResultList: Decodable {
let results: [SomeResult]
init(from decoder: Decoder) throws {
results = try decoder.singleValueContainer().decode([SomeResult].self)
}
}
struct SomeResult: Decodable {
}
예시2
각 최종 primitive type 에서 케이스를 나눠서 self에 넣어주고 싶을 때
ex) enum의 init에서 singleValueContainer 사용
internal enum Animal: String, Decodable {
case dog = "DOG"
case cat = "CAT"
case unknown
internal init(from decoder: Decoder) throws {
if let rawValue = try? decoder.singleValueContainer().decode(RawValue.self),
let animal = Animal(rawValue: rawValue) {
self = animal
} else {
self = .unknown
}
}
}
3. UnkeyedDecodingContainer
- key가 없는 값들을 보유하기에 적합한 Container
- 순서대로 decode 된다.
예시
아래와 같은 key가 없는 array 형태의 json 파일을 디코딩 할 때 적합
["a", "b", 1, 3, 0.3]
특이사항: decode 함수가 mutable 이다!!
struct ArrayDecoder: Decodable {
let a: String
let b: String
let c: Int?
let d: Bool
let e: Double
enum CodingKeys: CodingKey {
case a
case b
case c
case d
case e
}
init(from decoder: Decoder) throws {
// decode 함수를 부르면 var로 바꾸라고 한다.
// 다른 아이들과 다르게 decode 함수가 mutating이다.
// 그 이유는 decode하면 그 아이가 array에서 pop(?)되기 때문
var container = try decoder.unkeyedContainer()
self.a = try container.decode(String.self)
self.b = try container.decode(String.self)
// decodeIfPresent 에서 실패해서 nil이 나오면 pop되지 않는다.
self.c = try container.decodeIfPresent(Int.self)
// 값이 nil이면 true, 아니면 false
self.d = try container.decodeNil()
self.e = try container.decode(Double.self)
}
}
'개발 > iOS' 카테고리의 다른 글
타입 나눠서 decoding하기 (0) | 2023.01.14 |
---|---|
KeyedDecodingContainer의 메소드들 - decode, nestedContainer, superDecoder 등 (0) | 2023.01.14 |
WWDC 2022 - Meet Swift Async Algorithms (0) | 2022.07.01 |
WWDC 2022 - Get more mileage out of your app with CarPlay (0) | 2022.07.01 |
WWDC 2022 - Platforms State of the Union (0) | 2022.06.30 |