enum Block: Codable {
case text(TextBlock)
case image(ImageBlock)
case video(VideoBlock)
enum CodingKeys: String, CodingKey {
case type
}
enum BlockType: String, Codable {
case text
case image
case video
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(BlockType.self, forKey: .type)
let singleValue = try decoder.singleValueContainer()
switch type {
case .text:
let text = try singleValue.decode(TextBlock.self)
self = .text(text)
case .image:
let image = try singleValue.decode(ImageBlock.self)
self = .image(image)
case .video:
let video = try singleValue.decode(VideoBlock.self)
self = .video(video)
}
}
func encode(to encoder: Encoder) throws {
switch self {
case .text(let block):
try block.encode(to: encoder)
case .image(let block):
try block.encode(to: encoder)
case .video(let block):
try block.encode(to: encoder)
}
}
}
Codable
- 자료를 쉽게 저장하고 불러올수있도록 해준다.
- Json 파일을 읽거나 저장하도록 도와준다.
- Codable을 붙이면 자동으로 파일에 저장하거나 파일에서 불러올수있게 해줌
Enum - case text(TextBlock)
- text라는 case에 TextBlock 이라는 추가정보가 있는 것임
- text를 선택할 때 TextBlock이라는 추가정보가 있어야함
CodingKey
enum CodingKeys: String, CodingKey {
case type
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(BlockType.self, forKey: .type)
let singleValue = try decoder.singleValueContainer()
switch type {
case .text:
let text = try singleValue.decode(TextBlock.self)
self = .text(text)
case .image:
let image = try singleValue.decode(ImageBlock.self)
self = .image(image)
case .video:
let video = try singleValue.decode(VideoBlock.self)
self = .video(video)
}
}
func encode(to encoder: Encoder) throws {
switch self {
case .text(let block):
try block.encode(to: encoder)
case .image(let block):
try block.encode(to: encoder)
case .video(let block):
try block.encode(to: encoder)
}
}
- json 파일이나 데이터에서 type이라는 이름으로 저장되어있다고 알려주는 것
- 이 코드에서는 저장할 때 다른 타입과 값을 저장하기 위해서 init(from:)과 func encode를 구현함
- container(keyedBy:) 쓸 때는, 거기에 넘기는 타입이 반드시 CodingKey 프로토콜을 따라야 한다!
///json 값
{
"type": "text"
}
struct Block: Codable {
let blockType: String // 변수 이름이 'type'이 아님
enum CodingKeys: String, CodingKey {
case blockType = "type" // JSON의 "type"을 blockType 변수에 매칭
}
}
- CodingKey는 json의 키 이름과 다르게 저장하고싶을 때 사용된다.
- container(keyedBy:) 쓸 때는, 거기에 넘기는 타입이 반드시 CodingKey 프로토콜을 따라야 한다!
Decoder
let container = try decoder.container(keyedBy: CodingKeys.self)
- decorder
- 데이터나 파일을 코드 안의 변수로 바꿔주는 도구
- decorder는 데이터를 읽는 기계
let container = try decoder.container(keyedBy: CodingKeys.self)
- json 안에서 key-value를 꺼내올 준비를 한다.
- CodingKeys에 있는 키와 값을 꺼낼 준비를 한다.
decoder.singleValueContainer()
- TextBlock이나 ImageBlock 같은 딱하나 있는 덩어리를 꺼내기 위함
let text = try singleValue.decode(TextBlock.self)
- 아까 만든 singleValueContainer에서 TextBlock 타입으로 데이터를 꺼내는 거야.
- 즉, 저장돼 있던 JSON 데이터를 읽어서 TextBlock이라는 진짜 객체로 복구하는 거지.
Encoder
try block.encode(to: encoder)
- 변수를 파일이나 데이터로 저장
- encode(to:)는 자동으로 데이터를 json파일로 저장함
호출하는 법
let block = try JSONDecoder().decode(Block.self, from: jsonData)
- init(from:)을 해주지 않아도 Block.self를 썼으니 Swift에서 알아서 내가 커스텀한 init(from:)을 호출한다.
'swift' 카테고리의 다른 글
Codable 활용하여 함수 만들기 (0) | 2025.04.28 |
---|---|
[tapGesture.cancelsTouchesInView = false] <- 이게 뭔데 (1) | 2025.04.28 |
UIView의 draw(_:)는 그림을 그리는 함수이다. (0) | 2025.04.18 |
[Swift] Combine (0) | 2025.02.28 |
[Swift] map, flatMap, compactMap, reduce (0) | 2025.02.27 |