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
- SWIFT
- windowScene
- Automatically manage signing
- RxCocoa
- App Signing
- Dependency Rule
- Concurrent
- 로버트마틴형
- 메모리 접근 충돌
- 클린아키텍쳐
- 대머리깃허브
- ios
- Large File Storage
- iOS Target
- Ribs
- memory safety
- coordinateSpace
- iOS 버전 점유율
- Apple Certificate
- RxSwift
- 잡초가득블로그
- swiftdocs
- in-out
- UICoordinateSpace
- Dispatch.main.sync
- conflicting access to memory
- rib
- RIBs Tutorial
- Github file size
- Git Large File Storage
Archives
- Today
- Total
빙수왕의 개발일지
KeyedDecodingContainer의 메소드들 - decode, nestedContainer, superDecoder 등 본문
개발/iOS
KeyedDecodingContainer의 메소드들 - decode, nestedContainer, superDecoder 등
빙수킹 2023. 1. 14. 18:58KeyedDecodingContainer 주요 메소드들
- decode(_:forKey:)
- decodeIfPresent(_:forKey:)
- decodeNil(forKey:)
- nestedContainer(keyedBy:forKey:)
- nestedUnkeyedContainer(forKey:)
- superDecoder()
- superDecoder(forKey:)
그 외 - configuration을 받는 메소드들
- decode(forKey:configuration:)
음.. 자세히는 안봤지만,
decode 할 때 configuration 객체를 내가 커스텀해서 만들고 그걸 사용해서 decode할 수 있도록 해주는 메소드인 것 같다.
https://www.andyibanez.com/posts/the-mysterious-codablewithconfiguration-protocol/ 여기 보면 자세한 내용 있음
1. decode vs decodeIfPresent
Struct에 Decodable을 준수하면 기본으로 만들어주는 init(from:) 에서,
각 프로퍼티가 Optional인 경우는 decodeIfPresent
를 사용하고 아닌 경우는 decode
를 사용한다.
decode
- 리턴타입이 non Optional
- 해당 key나 value가 없으면
DecodingError.KeyNotFound
,DecodingError.valueNotFound
와 같은 에러가 발생하면서 해당 객체의 Decoding에 실패한다.
decodeIfPresent
- 리턴타입이 Optional
- 해당 키가 없어도
DecodingError.KeyNotFound
가 발생하지 않는다. 대신 nil을 리턴한다. - 프로퍼티를 Optional로 만들고 싶지 않은 경우에는, default value를 제공하면 된다.
예시1 - 각 Optional, nonOptional 프로퍼티에서 사용되는 함수들
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
}
// Default init..
// decode: 키에 해당하는 값이 없으면 Decoding Error가 발생하고 파싱에 실패한다.
// 키가 여기 없는데 서버에서 추가로 내려오는건 상관 없다.
// 프로퍼티들 중 Optional인 아이들은 기본 init에서 decodeIfPresent로 구현된다.
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 - 각 프로퍼티를 Optional이 아니면서 디코딩도 성공하도록 만들기
아래와 같이 default value를 제공하면 된다.
// 서버에서 어떻게 내려올지 확실하지 않다면..? 값이 없어도 파싱에 성공하고싶다면?
// 해당하는 키가 없어도 Decoding Error가 발생하지 않게 하고싶다면?
// decodeIfPresent 사용하면 된다.
// 대신 decodeIfPresent의 리턴형은 Optional이므로, 각 property들을 Optional로 지정하거나 기본값을 세팅해줘야 한다.
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.title = try container.decodeIfPresent(String.self, forKey: .title) ?? "no title"
self.description = try container.decodeIfPresent(String.self, forKey: .description) ?? "no description"
self.ingredients = try container.decodeIfPresent([String].self, forKey: .ingredients) ?? []
self.image = try container.decodeIfPresent(String.self, forKey: .image) ?? ""
self.id = try container.decodeIfPresent(Int.self, forKey: .id) ?? -1
}
2. decodeNil(forKey:)
nil이면 true, 아니면 false 값 리턴
3. nestedContainer
말 그대로 nested - 현재 struct의 한 껍질 안의 값을 꺼내고 싶을 때 사용
예시
json 이 다음과 같고, 가장 밖의 struct에서 result.name을 바로 넣고싶으면?
{
"result": {
"name": "Lina"
}
}
다음과 같이 nestedContainer을 사용하면 된다.
struct MyResult: Decodable {
public var name: String?
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let result = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .result)
self.name = try result.decodeIfPresent(String.self, forKey: .name)
}
enum CodingKeys: CodingKey {
case result
case name
}
}
4. superDecoder
container에서 super
키를 가진 아이의 decoder을 반환한다.
사용해본 적은 없는데..
찾아보니 Decodable
한 SuperClass를 상속받은 SubClass에서 사용하는 것 같다.
SubClass의 init(from:)
에서 super.init(from:)
을 불러주기 위한 용도..?
예시
class FullSub: FullSuper {
var string: String?
private enum CodingKeys: String, CodingKey { case string }
override init() { super.init() }
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
// super.init에 사용하기 위한 super의 decoder
let superdecoder = try container.superDecoder()
try super.init(from: superdecoder)
string = try container.decode(String.self, forKey: .string)
}
}
class FullSuper: Codable {
var id: UUID?
init() {}
private enum CodingKeys: String, CodingKey { case id }
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
}
}
'개발 > iOS' 카테고리의 다른 글
타입 나눠서 decoding하기 (0) | 2023.01.14 |
---|---|
Decoder 3가지 메소드 정리 (Container 종류) (1) | 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 |